1 # -*- Mode: Python; py-indent-offset: 4 -*-
6 py_ssize_t_clean = False
8 class ArgTypeError(Exception):
11 class ArgTypeNotFoundError(ArgTypeError):
14 class ArgTypeConfigurationError(ArgTypeError):
19 """Nicely format a C variable list"""
22 def add(self, ctype, name):
23 if self.vars.has_key(ctype):
24 self.vars[ctype] = self.vars[ctype] + (name,)
26 self.vars[ctype] = (name,)
29 for type in self.vars.keys():
33 ret.append(string.join(self.vars[type], ', '))
37 return string.join(ret, '')
41 """A class that holds information about variable defs, code
42 snippets, etcd for use in writing out the function/method
45 self.varlist = VarList()
47 self.parselist = ['', 'kwlist']
52 def get_parselist(self):
53 return string.join(self.parselist, ', ')
54 def get_codebefore(self):
55 return string.join(self.codebefore, '')
56 def get_codeafter(self):
57 return string.join(self.codeafter, '')
58 def get_arglist(self):
59 return string.join(self.arglist, ', ')
60 def get_varlist(self):
61 return str(self.varlist)
63 ret = ' static char *kwlist[] = { %s };\n' % \
64 string.join(self.kwlist + [ 'NULL' ], ', ')
65 if not self.get_varlist():
69 def add_parselist(self, codes, parseargs, keywords):
70 self.parsestr = self.parsestr + codes
72 self.parselist.append(arg)
74 if keyword.iskeyword(kw):
76 self.kwlist.append('"%s"' % kw)
79 def write_param(self, ptype, pname, pdflt, pnull, info):
80 """Add code to the WrapperInfo instance to handle
82 raise RuntimeError("write_param not implemented for %s"
83 % self.__class__.__name__)
84 def write_return(self, ptype, ownsreturn, info):
85 """Adds a variable named ret of the return type to
86 info.varlist, and add any required code to info.codeafter to
87 convert the return value to a python object."""
88 raise RuntimeError("write_return not implemented for %s"
89 % self.__class__.__name__)
91 class NoneArg(ArgType):
92 def write_return(self, ptype, ownsreturn, info):
93 info.codeafter.append(' Py_INCREF(Py_None);\n' +
96 class StringArg(ArgType):
97 def write_param(self, ptype, pname, pdflt, pnull, info):
99 if pdflt != 'NULL': pdflt = '"' + pdflt + '"'
100 info.varlist.add('char', '*' + pname + ' = ' + pdflt)
102 info.varlist.add('char', '*' + pname)
103 info.arglist.append(pname)
105 info.add_parselist('z', ['&' + pname], [pname])
107 info.add_parselist('s', ['&' + pname], [pname])
108 def write_return(self, ptype, ownsreturn, info):
110 # have to free result ...
111 info.varlist.add('gchar', '*ret')
112 info.codeafter.append(' if (ret) {\n' +
113 ' PyObject *py_ret = PyString_FromString(ret);\n' +
115 ' return py_ret;\n' +
117 ' Py_INCREF(Py_None);\n' +
120 info.varlist.add('const gchar', '*ret')
121 info.codeafter.append(' if (ret)\n' +
122 ' return PyString_FromString(ret);\n'+
123 ' Py_INCREF(Py_None);\n' +
126 class UCharArg(ArgType):
127 # allows strings with embedded NULLs.
128 def write_param(self, ptype, pname, pdflt, pnull, info):
130 info.varlist.add('guchar', '*' + pname + ' = "' + pdflt + '"')
132 info.varlist.add('guchar', '*' + pname)
134 info.varlist.add('Py_ssize_t', pname + '_len')
136 info.varlist.add('int', pname + '_len')
137 info.arglist.append(pname)
139 info.add_parselist('z#', ['&' + pname, '&' + pname + '_len'],
142 info.add_parselist('s#', ['&' + pname, '&' + pname + '_len'],
145 class CharArg(ArgType):
146 def write_param(self, ptype, pname, pdflt, pnull, info):
148 info.varlist.add('char', pname + " = '" + pdflt + "'")
150 info.varlist.add('char', pname)
151 info.arglist.append(pname)
152 info.add_parselist('c', ['&' + pname], [pname])
153 def write_return(self, ptype, ownsreturn, info):
154 info.varlist.add('gchar', 'ret')
155 info.codeafter.append(' return PyString_FromStringAndSize(&ret, 1);')
156 class GUniCharArg(ArgType):
157 ret_tmpl = ('#if !defined(Py_UNICODE_SIZE) || Py_UNICODE_SIZE == 2\n'
158 ' if (ret > 0xffff) {\n'
159 ' PyErr_SetString(PyExc_RuntimeError, "returned character can not be represented in 16-bit unicode");\n'
163 ' py_ret = (Py_UNICODE)ret;\n'
164 ' return PyUnicode_FromUnicode(&py_ret, 1);\n')
165 def write_param(self, ptype, pname, pdflt, pnull, info):
167 info.varlist.add('gunichar', pname + " = '" + pdflt + "'")
169 info.varlist.add('gunichar', pname)
170 info.arglist.append(pname)
171 info.add_parselist('O&', ['pyg_pyobj_to_unichar_conv', '&' + pname], [pname])
172 def write_return(self, ptype, ownsreturn, info):
173 info.varlist.add('gunichar', 'ret')
174 info.varlist.add('Py_UNICODE', 'py_ret')
175 info.codeafter.append(self.ret_tmpl)
178 class IntArg(ArgType):
179 def write_param(self, ptype, pname, pdflt, pnull, info):
181 info.varlist.add('int', pname + ' = ' + pdflt)
183 info.varlist.add('int', pname)
184 info.arglist.append(pname)
185 info.add_parselist('i', ['&' + pname], [pname])
186 def write_return(self, ptype, ownsreturn, info):
187 info.varlist.add('int', 'ret')
188 info.codeafter.append(' return PyInt_FromLong(ret);')
190 class UIntArg(ArgType):
191 dflt = (' if (py_%(name)s) {\n'
192 ' if (PyLong_Check(py_%(name)s))\n'
193 ' %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
194 ' else if (PyInt_Check(py_%(name)s))\n'
195 ' %(name)s = PyInt_AsLong(py_%(name)s);\n'
197 ' PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
198 ' if (PyErr_Occurred())\n'
201 before = (' if (PyLong_Check(py_%(name)s))\n'
202 ' %(name)s = PyLong_AsUnsignedLong(py_%(name)s);\n'
203 ' else if (PyInt_Check(py_%(name)s))\n'
204 ' %(name)s = PyInt_AsLong(py_%(name)s);\n'
206 ' PyErr_SetString(PyExc_TypeError, "Parameter \'%(name)s\' must be an int or a long");\n'
207 ' if (PyErr_Occurred())\n'
209 def write_param(self, ptype, pname, pdflt, pnull, info):
213 info.varlist.add(ptype, pname + ' = ' + pdflt)
214 info.codebefore.append(self.dflt % {'name':pname})
215 info.varlist.add('PyObject', "*py_" + pname + ' = NULL')
216 info.arglist.append(pname)
217 info.add_parselist('O', ['&py_' + pname], [pname])
218 def write_return(self, ptype, ownsreturn, info):
219 info.varlist.add(ptype, 'ret')
220 info.codeafter.append(' return PyLong_FromUnsignedLong(ret);')
222 class SizeArg(ArgType):
224 if struct.calcsize('P') <= struct.calcsize('l'):
229 def write_param(self, ptype, pname, pdflt, pnull, info):
231 info.varlist.add(ptype, pname + ' = ' + pdflt)
233 info.varlist.add(ptype, pname)
234 info.arglist.append(pname)
236 info.add_parselist('k', ['&' + pname], [pname])
238 info.add_parselist('K', ['&' + pname], [pname])
239 def write_return(self, ptype, ownsreturn, info):
240 info.varlist.add(ptype, 'ret')
242 info.codeafter.append(' return PyLong_FromUnsignedLongLong(ret);\n')
244 info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n')
246 class SSizeArg(ArgType):
248 if struct.calcsize('P') <= struct.calcsize('l'):
253 def write_param(self, ptype, pname, pdflt, pnull, info):
255 info.varlist.add(ptype, pname + ' = ' + pdflt)
257 info.varlist.add(ptype, pname)
258 info.arglist.append(pname)
260 info.add_parselist('l', ['&' + pname], [pname])
262 info.add_parselist('L', ['&' + pname], [pname])
263 def write_return(self, ptype, ownsreturn, info):
264 info.varlist.add(ptype, 'ret')
266 info.codeafter.append(' return PyLong_FromLongLong(ret);\n')
268 info.codeafter.append(' return PyLong_FromLong(ret);\n')
270 class LongArg(ArgType):
271 def write_param(self, ptype, pname, pdflt, pnull, info):
273 info.varlist.add(ptype, pname + ' = ' + pdflt)
275 info.varlist.add(ptype, pname)
276 info.arglist.append(pname)
277 info.add_parselist('l', ['&' + pname], [pname])
278 def write_return(self, ptype, ownsreturn, info):
279 info.varlist.add(ptype, 'ret')
280 info.codeafter.append(' return PyInt_FromLong(ret);\n')
282 class BoolArg(IntArg):
283 def write_return(self, ptype, ownsreturn, info):
284 info.varlist.add('int', 'ret')
285 info.codeafter.append(' return PyBool_FromLong(ret);\n')
287 class TimeTArg(ArgType):
288 def write_param(self, ptype, pname, pdflt, pnull, info):
290 info.varlist.add('time_t', pname + ' = ' + pdflt)
292 info.varlist.add('time_t', pname)
293 info.arglist.append(pname)
294 info.add_parselist('i', ['&' + pname], [pname])
295 def write_return(self, ptype, ownsreturn, info):
296 info.varlist.add('time_t', 'ret')
297 info.codeafter.append(' return PyInt_FromLong(ret);')
299 class ULongArg(ArgType):
300 def write_param(self, ptype, pname, pdflt, pnull, info):
302 info.varlist.add('unsigned long', pname + ' = ' + pdflt)
304 info.varlist.add('unsigned long', pname)
305 info.arglist.append(pname)
306 info.add_parselist('k', ['&' + pname], [pname])
307 def write_return(self, ptype, ownsreturn, info):
308 info.varlist.add(ptype, 'ret')
309 info.codeafter.append(' return PyLong_FromUnsignedLong(ret);\n')
311 class UInt32Arg(ULongArg):
312 def write_param(self, ptype, pname, pdflt, pnull, info):
313 ULongArg.write_param(self, ptype, pname, pdflt, pnull, info)
314 ## if sizeof(unsigned long) > sizeof(unsigned int), we need to
315 ## check the value is within guint32 range
316 if struct.calcsize('L') > struct.calcsize('I'):
317 info.codebefore.append((
318 ' if (%(pname)s > G_MAXUINT32) {\n'
319 ' PyErr_SetString(PyExc_ValueError,\n'
320 ' "Value out of range in conversion of"\n'
321 ' " %(pname)s parameter to unsigned 32 bit integer");\n'
325 class Int64Arg(ArgType):
326 def write_param(self, ptype, pname, pdflt, pnull, info):
328 info.varlist.add('gint64', pname + ' = ' + pdflt)
330 info.varlist.add('gint64', pname)
331 info.arglist.append(pname)
332 info.add_parselist('L', ['&' + pname], [pname])
333 def write_return(self, ptype, ownsreturn, info):
334 info.varlist.add('gint64', 'ret')
335 info.codeafter.append(' return PyLong_FromLongLong(ret);')
337 class UInt64Arg(ArgType):
338 dflt = ' if (py_%(name)s)\n' \
339 ' %(name)s = PyLong_AsUnsignedLongLong(py_%(name)s);\n'
340 before = ' %(name)s = PyLong_AsUnsignedLongLong(py_%(name)s);\n'
341 def write_param(self, ptype, pname, pdflt, pnull, info):
343 info.varlist.add('guint64', pname + ' = ' + pdflt)
344 info.codebefore.append(self.dflt % {'name':pname})
346 info.varlist.add('guint64', pname)
347 info.codebefore.append(self.before % {'name':pname})
348 info.varlist.add('PyObject', "*py_" + pname + ' = NULL')
349 info.arglist.append(pname)
350 info.add_parselist('O!', ['&PyLong_Type', '&py_' + pname], [pname])
351 def write_return(self, ptype, ownsreturn, info):
352 info.varlist.add('guint64', 'ret')
353 info.codeafter.append(' return PyLong_FromUnsignedLongLong(ret);')
356 class DoubleArg(ArgType):
357 def write_param(self, ptype, pname, pdflt, pnull, info):
359 info.varlist.add('double', pname + ' = ' + pdflt)
361 info.varlist.add('double', pname)
362 info.arglist.append(pname)
363 info.add_parselist('d', ['&' + pname], [pname])
364 def write_return(self, ptype, ownsreturn, info):
365 info.varlist.add('double', 'ret')
366 info.codeafter.append(' return PyFloat_FromDouble(ret);')
368 class FileArg(ArgType):
369 nulldflt = (' if (py_%(name)s == Py_None)\n'
370 ' %(name)s = NULL;\n'
371 ' else if (py_%(name)s && PyFile_Check(py_%(name)s)\n'
372 ' %s = PyFile_AsFile(py_%(name)s);\n'
373 ' else if (py_%(name)s) {\n'
374 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n'
377 null = (' if (py_%(name)s && PyFile_Check(py_%(name)s)\n'
378 ' %(name)s = PyFile_AsFile(py_%(name)s);\n'
379 ' else if (py_%(name)s != Py_None) {\n'
380 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a file object or None");\n'
383 dflt = (' if (py_%(name)s)\n'
384 ' %(name)s = PyFile_AsFile(py_%(name)s);\n')
385 def write_param(self, ptype, pname, pdflt, pnull, info):
388 info.varlist.add('FILE', '*' + pname + ' = ' + pdflt)
389 info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
390 info.codebefore.append(self.nulldflt % {'name':pname})
392 info.varlist.add('FILE', '*' + pname + ' = NULL')
393 info.varlist.add('PyObject', '*py_' + pname)
394 info.codebefore.append(self.null & {'name':pname})
395 info.arglist.appned(pname)
396 info.add_parselist('O', ['&py_' + pname], [pname])
399 info.varlist.add('FILE', '*' + pname + ' = ' + pdflt)
400 info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
401 info.codebefore.append(self.dflt % {'name':pname})
402 info.arglist.append(pname)
404 info.varlist.add('PyObject', '*' + pname)
405 info.arglist.append('PyFile_AsFile(' + pname + ')')
406 info.add_parselist('O!', ['&PyFile_Type', '&' + pname], [pname])
407 def write_return(self, ptype, ownsreturn, info):
408 info.varlist.add('FILE', '*ret')
409 info.codeafter.append(' if (ret)\n' +
410 ' return PyFile_FromFile(ret, "", "", fclose);\n' +
411 ' Py_INCREF(Py_None);\n' +
414 class EnumArg(ArgType):
415 enum = (' if (pyg_enum_get_value(%(typecode)s, py_%(name)s, (gpointer)&%(name)s))\n'
417 def __init__(self, enumname, typecode):
418 self.enumname = enumname
419 self.typecode = typecode
420 def write_param(self, ptype, pname, pdflt, pnull, info):
422 info.varlist.add(self.enumname, pname + ' = ' + pdflt)
424 info.varlist.add(self.enumname, pname)
425 info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
426 info.codebefore.append(self.enum % { 'typecode': self.typecode,
428 info.arglist.append(pname)
429 info.add_parselist('O', ['&py_' + pname], [pname]);
430 def write_return(self, ptype, ownsreturn, info):
431 info.varlist.add('gint', 'ret')
432 info.codeafter.append(' return pyg_enum_from_gtype(%s, ret);' % self.typecode)
434 class FlagsArg(ArgType):
435 flag = (' if (%(default)spyg_flags_get_value(%(typecode)s, py_%(name)s, (gpointer)&%(name)s))\n'
437 def __init__(self, flagname, typecode):
438 self.flagname = flagname
439 self.typecode = typecode
440 def write_param(self, ptype, pname, pdflt, pnull, info):
442 info.varlist.add(self.flagname, pname + ' = ' + pdflt)
443 default = "py_%s && " % (pname,)
445 info.varlist.add(self.flagname, pname)
447 info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
448 info.codebefore.append(self.flag % {'default':default,
449 'typecode':self.typecode,
451 info.arglist.append(pname)
452 info.add_parselist('O', ['&py_' + pname], [pname])
453 def write_return(self, ptype, ownsreturn, info):
454 info.varlist.add('guint', 'ret')
455 info.codeafter.append(' return pyg_flags_from_gtype(%s, ret);' % self.typecode)
457 class ObjectArg(ArgType):
458 # should change these checks to more typesafe versions that check
459 # a little further down in the class heirachy.
460 nulldflt = (' if ((PyObject *)py_%(name)s == Py_None)\n'
461 ' %(name)s = NULL;\n'
462 ' else if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n'
463 ' %(name)s = %(cast)s(py_%(name)s->obj);\n'
464 ' else if (py_%(name)s) {\n'
465 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
468 null = (' if (py_%(name)s && pygobject_check(py_%(name)s, &Py%(type)s_Type))\n'
469 ' %(name)s = %(cast)s(py_%(name)s->obj);\n'
470 ' else if ((PyObject *)py_%(name)s != Py_None) {\n'
471 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
474 dflt = ' if (py_%(name)s)\n' \
475 ' %(name)s = %(cast)s(py_%(name)s->obj);\n'
476 def __init__(self, objname, parent, typecode):
477 self.objname = objname
478 self.cast = string.replace(typecode, '_TYPE_', '_', 1)
480 def write_param(self, ptype, pname, pdflt, pnull, info):
483 info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt)
484 info.varlist.add('PyGObject', '*py_' + pname + ' = NULL')
485 info.codebefore.append(self.nulldflt % {'name':pname,
487 'type':self.objname})
489 info.varlist.add(self.objname, '*' + pname + ' = NULL')
490 info.varlist.add('PyGObject', '*py_' + pname)
491 info.codebefore.append(self.null % {'name':pname,
493 'type':self.objname})
494 if ptype.endswith('*'):
495 typename = ptype[:-1]
497 const, typename = typename.split('const-')
500 if typename != ptype:
501 info.arglist.append('(%s *) %s' % (ptype[:-1], pname))
503 info.arglist.append(pname)
505 info.add_parselist('O', ['&py_' + pname], [pname])
508 info.varlist.add(self.objname, '*' + pname + ' = ' + pdflt)
509 info.varlist.add('PyGObject', '*py_' + pname + ' = NULL')
510 info.codebefore.append(self.dflt % {'name':pname,
512 info.arglist.append(pname)
513 info.add_parselist('O!', ['&Py%s_Type' % self.objname,
514 '&py_' + pname], [pname])
516 info.varlist.add('PyGObject', '*' + pname)
517 info.arglist.append('%s(%s->obj)' % (self.cast, pname))
518 info.add_parselist('O!', ['&Py%s_Type' % self.objname,
519 '&' + pname], [pname])
520 def write_return(self, ptype, ownsreturn, info):
521 if ptype.endswith('*'):
522 typename = ptype[:-1]
524 const, typename = typename.split('const-')
527 info.varlist.add(typename, '*ret')
529 info.varlist.add('PyObject', '*py_ret')
530 info.codeafter.append(' py_ret = pygobject_new((GObject *)ret);\n'
531 ' if (ret != NULL)\n'
532 ' g_object_unref(ret);\n'
535 info.codeafter.append(' /* pygobject_new handles NULL checking */\n' +
536 ' return pygobject_new((GObject *)ret);')
538 class BoxedArg(ArgType):
539 # haven't done support for default args. Is it needed?
540 check = (' if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n'
541 ' %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n'
543 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n'
546 null = (' if (pyg_boxed_check(py_%(name)s, %(typecode)s))\n'
547 ' %(name)s = pyg_boxed_get(py_%(name)s, %(typename)s);\n'
548 ' else if (py_%(name)s != Py_None) {\n'
549 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n'
552 def __init__(self, ptype, typecode):
553 self.typename = ptype
554 self.typecode = typecode
555 def write_param(self, ptype, pname, pdflt, pnull, info):
557 info.varlist.add(self.typename, '*' + pname + ' = NULL')
558 info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
559 info.codebefore.append(self.null % {'name': pname,
560 'typename': self.typename,
561 'typecode': self.typecode})
563 info.varlist.add(self.typename, '*' + pname + ' = NULL')
564 info.varlist.add('PyObject', '*py_' + pname)
565 info.codebefore.append(self.check % {'name': pname,
566 'typename': self.typename,
567 'typecode': self.typecode})
569 typename = ptype[:-1]
570 if typename[:6] == 'const-': typename = typename[6:]
571 if typename != self.typename:
572 info.arglist.append('(%s *)%s' % (ptype[:-1], pname))
574 info.arglist.append(pname)
576 info.arglist.append(pname)
577 info.add_parselist('O', ['&py_' + pname], [pname])
578 ret_tmpl = ' /* pyg_boxed_new handles NULL checking */\n' \
579 ' return pyg_boxed_new(%(typecode)s, %(ret)s, %(copy)s, TRUE);'
580 def write_return(self, ptype, ownsreturn, info):
582 decl_type = self.typename
584 if ptype[:6] == 'const-':
585 decl_type = 'const ' + self.typename
586 ret = '(%s*) ret' % (self.typename,)
587 info.varlist.add(decl_type, '*ret')
589 info.varlist.add(self.typename, 'ret')
591 ownsreturn = 0 # of course it can't own a ref to a local var ...
592 info.codeafter.append(self.ret_tmpl %
593 { 'typecode': self.typecode,
595 'copy': ownsreturn and 'FALSE' or 'TRUE'})
597 class CustomBoxedArg(ArgType):
598 # haven't done support for default args. Is it needed?
599 null = (' if (%(check)s(py_%(name)s))\n'
600 ' %(name)s = %(get)s(py_%(name)s);\n'
601 ' else if (py_%(name)s != Py_None) {\n'
602 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(type)s or None");\n'
605 def __init__(self, ptype, pytype, getter, new):
608 self.checker = 'Py' + ptype + '_Check'
610 def write_param(self, ptype, pname, pdflt, pnull, info):
612 info.varlist.add(ptype[:-1], '*' + pname + ' = NULL')
613 info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
614 info.codebefore.append(self.null % {'name': pname,
616 'check': self.checker,
618 info.arglist.append(pname)
619 info.add_parselist('O', ['&py_' + pname], [pname])
621 info.varlist.add('PyObject', '*' + pname)
622 info.arglist.append(self.getter + '(' + pname + ')')
623 info.add_parselist('O!', ['&' + self.pytype, '&' + pname], [pname])
624 def write_return(self, ptype, ownsreturn, info):
625 info.varlist.add(ptype[:-1], '*ret')
626 info.codeafter.append(' if (ret)\n' +
627 ' return ' + self.new + '(ret);\n' +
628 ' Py_INCREF(Py_None);\n' +
631 class PointerArg(ArgType):
632 # haven't done support for default args. Is it needed?
633 check = (' if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n'
634 ' %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n'
636 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s");\n'
639 null = (' if (pyg_pointer_check(py_%(name)s, %(typecode)s))\n'
640 ' %(name)s = pyg_pointer_get(py_%(name)s, %(typename)s);\n'
641 ' else if (py_%(name)s != Py_None) {\n'
642 ' PyErr_SetString(PyExc_TypeError, "%(name)s should be a %(typename)s or None");\n'
645 def __init__(self, ptype, typecode):
646 self.typename = ptype
647 self.typecode = typecode
648 def write_param(self, ptype, pname, pdflt, pnull, info):
650 info.varlist.add(self.typename, '*' + pname + ' = NULL')
651 info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
652 info.codebefore.append(self.null % {'name': pname,
653 'typename': self.typename,
654 'typecode': self.typecode})
656 info.varlist.add(self.typename, '*' + pname + ' = NULL')
657 info.varlist.add('PyObject', '*py_' + pname)
658 info.codebefore.append(self.check % {'name': pname,
659 'typename': self.typename,
660 'typecode': self.typecode})
661 info.arglist.append(pname)
662 info.add_parselist('O', ['&py_' + pname], [pname])
663 def write_return(self, ptype, ownsreturn, info):
665 info.varlist.add(self.typename, '*ret')
666 info.codeafter.append(' /* pyg_pointer_new handles NULL checking */\n' +
667 ' return pyg_pointer_new(' + self.typecode + ', ret);')
669 info.varlist.add(self.typename, 'ret')
670 info.codeafter.append(' /* pyg_pointer_new handles NULL checking */\n' +
671 ' return pyg_pointer_new(' + self.typecode + ', &ret);')
673 class AtomArg(IntArg):
674 dflt = ' if (py_%(name)s) {\n' \
675 ' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n' \
676 ' if (PyErr_Occurred())\n' \
679 atom = (' %(name)s = pygdk_atom_from_pyobject(py_%(name)s);\n'
680 ' if (PyErr_Occurred())\n'
682 def write_param(self, ptype, pname, pdflt, pnull, info):
684 info.varlist.add('GdkAtom', pname + ' = ' + pdflt)
685 info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
686 info.codebefore.append(self.dflt % {'name': pname})
688 info.varlist.add('GdkAtom', pname)
689 info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
690 info.codebefore.append(self.atom % {'name': pname})
691 info.arglist.append(pname)
692 info.add_parselist('O', ['&py_' + pname], [pname])
693 def write_return(self, ptype, ownsreturn, info):
694 info.varlist.add('GdkAtom', 'ret')
695 info.varlist.add('PyObject *', 'py_ret')
696 info.varlist.add('gchar *', 'name')
697 info.codeafter.append(' name = gdk_atom_name(ret);\n'
698 ' py_ret = PyString_FromString(name);\n'
702 class GTypeArg(ArgType):
703 gtype = (' if ((%(name)s = pyg_type_from_object(py_%(name)s)) == 0)\n'
705 def write_param(self, ptype, pname, pdflt, pnull, info):
706 info.varlist.add('GType', pname)
707 info.varlist.add('PyObject', '*py_' + pname + ' = NULL')
708 info.codebefore.append(self.gtype % {'name': pname})
709 info.arglist.append(pname)
710 info.add_parselist('O', ['&py_' + pname], [pname])
711 def write_return(self, ptype, ownsreturn, info):
712 info.varlist.add('GType', 'ret')
713 info.codeafter.append(' return pyg_type_wrapper_new(ret);')
715 # simple GError handler.
716 class GErrorArg(ArgType):
717 handleerror = (' if (pyg_error_check(&%(name)s))\n'
719 def write_param(self, ptype, pname, pdflt, pnull, info):
720 info.varlist.add('GError', '*' + pname + ' = NULL')
721 info.arglist.append('&' + pname)
722 info.codeafter.append(self.handleerror % { 'name': pname })
724 class GtkTreePathArg(ArgType):
725 # haven't done support for default args. Is it needed?
726 normal = (' %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
727 ' if (!%(name)s) {\n'
728 ' PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n'
731 null = (' if (py_%(name)s != Py_None) {\n'
732 ' %(name)s = pygtk_tree_path_from_pyobject(py_%(name)s);\n'
733 ' if (!%(name)s) {\n'
734 ' PyErr_SetString(PyExc_TypeError, "could not convert %(name)s to a GtkTreePath");\n'
738 freepath = (' if (%(name)s)\n'
739 ' gtk_tree_path_free(%(name)s);\n')
742 def write_param(self, ptype, pname, pdflt, pnull, info):
744 info.varlist.add('GtkTreePath', '*' + pname + ' = NULL')
745 info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
746 info.codebefore.append(self.null % {'name': pname})
747 info.arglist.append(pname)
748 info.add_parselist('O', ['&py_' + pname], [pname])
750 info.varlist.add('GtkTreePath', '*' + pname)
751 info.varlist.add('PyObject', '*py_' + pname)
752 info.codebefore.append(self.normal % {'name': pname})
753 info.arglist.append(pname)
754 info.add_parselist('O', ['&py_' + pname], [pname])
755 info.codeafter.append(self.freepath % {'name': pname})
756 def write_return(self, ptype, ownsreturn, info):
757 info.varlist.add('GtkTreePath', '*ret')
759 info.codeafter.append(' if (ret) {\n'
760 ' PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n'
761 ' gtk_tree_path_free(ret);\n'
764 ' Py_INCREF(Py_None);\n'
767 info.codeafter.append(' if (ret) {\n'
768 ' PyObject *py_ret = pygtk_tree_path_to_pyobject(ret);\n'
771 ' Py_INCREF(Py_None);\n'
774 class GdkRectanglePtrArg(ArgType):
775 normal = (' if (!pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s))\n'
777 null = (' if (py_%(name)s == Py_None)\n'
778 ' %(name)s = NULL;\n'
779 ' else if (pygdk_rectangle_from_pyobject(py_%(name)s, &%(name)s_rect))\n'
780 ' %(name)s = &%(name)s_rect;\n'
783 def write_param(self, ptype, pname, pdflt, pnull, info):
785 info.varlist.add('GdkRectangle', pname + '_rect = { 0, 0, 0, 0 }')
786 info.varlist.add('GdkRectangle', '*' + pname)
787 info.varlist.add('PyObject', '*py_' + pname + ' = Py_None')
788 info.add_parselist('O', ['&py_' + pname], [pname])
789 info.arglist.append(pname)
790 info.codebefore.append(self.null % {'name': pname})
792 info.varlist.add('GdkRectangle', pname + ' = { 0, 0, 0, 0 }')
793 info.varlist.add('PyObject', '*py_' + pname)
794 info.add_parselist('O', ['&py_' + pname], [pname])
795 info.arglist.append('&' + pname)
796 info.codebefore.append(self.normal % {'name': pname})
798 class GdkRectangleArg(ArgType):
799 def write_return(self, ptype, ownsreturn, info):
800 info.varlist.add('GdkRectangle', 'ret')
801 info.codeafter.append(' return pyg_boxed_new(GDK_TYPE_RECTANGLE, &ret, TRUE, TRUE);')
803 class PyObjectArg(ArgType):
804 def write_param(self, ptype, pname, pdflt, pnull, info):
805 info.varlist.add('PyObject', '*' + pname)
806 info.add_parselist('O', ['&' + pname], [pname])
807 info.arglist.append(pname)
808 def write_return(self, ptype, ownsreturn, info):
809 info.varlist.add("PyObject", "*ret")
811 info.codeafter.append(' if (ret) {\n'
814 ' Py_INCREF(Py_None);\n'
817 info.codeafter.append(' if (!ret) ret = Py_None;\n'
821 class CairoArg(ArgType):
822 def write_param(self, ptype, pname, pdflt, pnull, info):
823 info.varlist.add('PycairoContext', '*' + pname)
824 info.add_parselist('O!', ['&PycairoContext_Type', '&' + pname], [pname])
825 info.arglist.append('%s->ctx' % pname)
826 def write_return(self, ptype, ownsreturn, info):
827 info.varlist.add("cairo_t", "*ret")
829 info.codeafter.append(' return PycairoContext_FromContext(ret, NULL, NULL);')
831 info.codeafter.append(' cairo_reference(ret);\n'
832 ' return PycairoContext_FromContext(ret, NULL, NULL);')
838 self.reverse_argtypes = {}
839 self.reverse_rettypes = {}
841 def register(self, ptype, handler, overwrite=False):
842 if not overwrite and ptype in self.argtypes:
844 self.argtypes[ptype] = handler
845 def register_reverse(self, ptype, handler):
846 self.reverse_argtypes[ptype] = handler
847 def register_reverse_ret(self, ptype, handler):
848 self.reverse_rettypes[ptype] = handler
850 def register_enum(self, ptype, typecode):
852 self.register(ptype, IntArg())
854 self.register(ptype, EnumArg(ptype, typecode))
855 def register_flag(self, ptype, typecode):
857 self.register(ptype, IntArg())
859 self.register(ptype, FlagsArg(ptype, typecode))
860 def register_object(self, ptype, parent, typecode):
861 oa = ObjectArg(ptype, parent, typecode)
862 self.register(ptype, oa) # in case I forget the * in the .defs
863 self.register(ptype+'*', oa)
864 self.register('const-'+ptype+'*', oa)
865 if ptype == 'GdkPixmap':
866 # hack to handle GdkBitmap synonym.
867 self.register('GdkBitmap', oa)
868 self.register('GdkBitmap*', oa)
869 def register_boxed(self, ptype, typecode):
870 if self.argtypes.has_key(ptype): return
871 arg = BoxedArg(ptype, typecode)
872 self.register(ptype, arg)
873 self.register(ptype+'*', arg)
874 self.register('const-'+ptype+'*', arg)
875 def register_custom_boxed(self, ptype, pytype, getter, new):
876 arg = CustomBoxedArg(ptype, pytype, getter, new)
877 self.register(ptype+'*', arg)
878 self.register('const-'+ptype+'*', arg)
879 def register_pointer(self, ptype, typecode):
880 arg = PointerArg(ptype, typecode)
881 self.register(ptype, arg)
882 self.register(ptype+'*', arg)
883 self.register('const-'+ptype+'*', arg)
885 def get(self, ptype):
887 return self.argtypes[ptype]
889 if ptype[:8] == 'GdkEvent' and ptype[-1] == '*':
890 return self.argtypes['GdkEvent*']
891 raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
892 def _get_reverse_common(self, ptype, registry):
893 props = dict(c_type=ptype)
895 return registry[ptype], props
898 handler = self.argtypes[ptype]
900 if ptype.startswith('GdkEvent') and ptype.endswith('*'):
901 handler = self.argtypes['GdkEvent*']
903 raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
904 if isinstance(handler, ObjectArg):
905 return registry['GObject*'], props
906 elif isinstance(handler, EnumArg):
907 props['typecode'] = handler.typecode
908 props['enumname'] = handler.enumname
909 return registry['GEnum'], props
910 elif isinstance(handler, FlagsArg):
911 props['typecode'] = handler.typecode
912 props['flagname'] = handler.flagname
913 return registry['GFlags'], props
914 elif isinstance(handler, BoxedArg):
915 props['typecode'] = handler.typecode
916 props['typename'] = handler.typename
917 return registry['GBoxed'], props
919 raise ArgTypeNotFoundError("No ArgType for %s" % (ptype,))
921 def get_reverse(self, ptype):
922 return self._get_reverse_common(ptype, self.reverse_argtypes)
924 def get_reverse_ret(self, ptype):
925 ret, props = self._get_reverse_common(ptype, self.reverse_rettypes)
926 if hasattr(ptype, 'optional') and ptype.optional:
927 if ret.supports_optional:
928 props['optional'] = True
930 raise ArgTypeNotFoundError("Unsupported 'optional' for %s"
934 def object_is_a(self, otype, parent):
935 if otype == None: return 0
936 if otype == parent: return 1
937 if not self.argtypes.has_key(otype): return 0
938 return self.object_is_a(self.get(otype).parent, parent)
940 matcher = ArgMatcher()
943 matcher.register(None, arg)
944 matcher.register('none', arg)
947 matcher.register('char*', arg)
948 matcher.register('gchar*', arg)
949 matcher.register('const-char*', arg)
950 matcher.register('char-const*', arg)
951 matcher.register('const-gchar*', arg)
952 matcher.register('gchar-const*', arg)
953 matcher.register('string', arg)
954 matcher.register('static_string', arg)
957 matcher.register('unsigned-char*', arg)
958 matcher.register('const-guchar*', arg)
959 matcher.register('const-guint8*', arg)
960 matcher.register('guchar*', arg)
963 matcher.register('char', arg)
964 matcher.register('gchar', arg)
965 matcher.register('guchar', arg)
968 matcher.register('gunichar', arg)
971 matcher.register('int', arg)
972 matcher.register('gint', arg)
973 matcher.register('short', arg)
974 matcher.register('gshort', arg)
975 matcher.register('gushort', arg)
976 matcher.register('gsize', SizeArg())
977 matcher.register('gssize', SSizeArg())
978 matcher.register('guint8', arg)
979 matcher.register('gint8', arg)
980 matcher.register('guint16', arg)
981 matcher.register('gint16', arg)
982 matcher.register('gint32', arg)
983 matcher.register('GTime', arg)
984 matcher.register('GSeekType', arg) # Hack, but we have no python wrapper
987 matcher.register('long', arg)
988 matcher.register('glong', arg)
991 matcher.register('guint', arg)
994 matcher.register('gboolean', arg)
997 matcher.register('time_t', arg)
999 matcher.register('guint32', UInt32Arg())
1002 matcher.register('gulong', arg)
1005 matcher.register('gint64', arg)
1006 matcher.register('long-long', arg)
1007 matcher.register('goffset', arg)
1010 matcher.register('guint64', arg)
1011 matcher.register('unsigned-long-long', arg)
1014 matcher.register('double', arg)
1015 matcher.register('gdouble', arg)
1016 matcher.register('float', arg)
1017 matcher.register('gfloat', arg)
1020 matcher.register('FILE*', arg)
1022 # enums, flags, objects
1024 matcher.register('GdkAtom', AtomArg())
1026 matcher.register('GType', GTypeArg())
1027 matcher.register('GtkType', GTypeArg())
1029 matcher.register('GError**', GErrorArg())
1030 matcher.register('GtkTreePath*', GtkTreePathArg())
1031 matcher.register('GdkRectangle*', GdkRectanglePtrArg())
1032 matcher.register('GtkAllocation*', GdkRectanglePtrArg())
1033 matcher.register('GdkRectangle', GdkRectangleArg())
1034 matcher.register('PyObject*', PyObjectArg())
1036 matcher.register('GdkNativeWindow', ULongArg())
1038 matcher.register_object('GObject', None, 'G_TYPE_OBJECT')
1042 matcher.register('cairo_t*', CairoArg())
1043 matcher.register_boxed("GClosure", "G_TYPE_CLOSURE")