home *** CD-ROM | disk | FTP | other *** search
/ Hackers Magazine 57 / CdHackersMagazineNr57.iso / Software / Multimedia / k3d-setup-0.7.11.0.exe / lib / site-packages / gtk-2.0 / codegen / codegen.py < prev    next >
Encoding:
Python Source  |  2007-11-01  |  67.8 KB  |  1,713 lines

  1. import getopt
  2. import keyword
  3. import os
  4. import string
  5. import sys
  6.  
  7. import argtypes
  8. import definitions
  9. import defsparser
  10. import override
  11. import reversewrapper
  12. import warnings
  13.  
  14. class Coverage(object):
  15.     def __init__(self, name):
  16.         self.name = name
  17.         self.wrapped = 0
  18.         self.not_wrapped = 0
  19.  
  20.     def declare_wrapped(self):
  21.         self.wrapped += 1
  22.  
  23.     def declare_not_wrapped(self):
  24.         self.not_wrapped += 1
  25.  
  26.     def printstats(self):
  27.         total = self.wrapped + self.not_wrapped
  28.         fd = sys.stderr
  29.         if total:
  30.             fd.write("***INFO*** The coverage of %s is %.2f%% (%i/%i)\n" %
  31.                      (self.name,
  32.                       float(self.wrapped*100)/total,
  33.                       self.wrapped,
  34.                       total))
  35.         else:
  36.             fd.write("***INFO*** There are no declared %s.\n" % self.name)
  37.  
  38. functions_coverage = Coverage("global functions")
  39. methods_coverage = Coverage("methods")
  40. vproxies_coverage = Coverage("virtual proxies")
  41. vaccessors_coverage = Coverage("virtual accessors")
  42. iproxies_coverage = Coverage("interface proxies")
  43.  
  44. def exc_info():
  45.     warnings.warn("deprecated", DeprecationWarning, stacklevel=2)
  46.     #traceback.print_exc()
  47.     etype, value, tb = sys.exc_info()
  48.     ret = ""
  49.     try:
  50.         sval = str(value)
  51.         if etype == argtypes.ArgTypeError:
  52.             ret = "No ArgType for %s" % (sval,)
  53.         else:
  54.             ret = sval
  55.     finally:
  56.         del etype, value, tb
  57.     return ret
  58.  
  59. def fixname(name):
  60.     if keyword.iskeyword(name):
  61.         return name + '_'
  62.     return name
  63.  
  64. class FileOutput:
  65.     '''Simple wrapper for file object, that makes writing #line
  66.     statements easier.''' # "
  67.     def __init__(self, fp, filename=None):
  68.         self.fp = fp
  69.         self.lineno = 1
  70.         if filename:
  71.             self.filename = filename
  72.         else:
  73.             self.filename = self.fp.name
  74.     # handle writing to the file, and keep track of the line number ...
  75.     def write(self, str):
  76.         self.fp.write(str)
  77.         self.lineno = self.lineno + string.count(str, '\n')
  78.     def writelines(self, sequence):
  79.         for line in sequence:
  80.             self.write(line)
  81.     def close(self):
  82.         self.fp.close()
  83.     def flush(self):
  84.         self.fp.flush()
  85.  
  86.     def setline(self, linenum, filename):
  87.         '''writes out a #line statement, for use by the C
  88.         preprocessor.''' # "
  89.         self.write('#line %d "%s"\n' % (linenum, filename))
  90.     def resetline(self):
  91.         '''resets line numbering to the original file'''
  92.         self.setline(self.lineno + 1, self.filename)
  93.  
  94. class Wrapper:
  95.     type_tmpl = (
  96.         'PyTypeObject G_GNUC_INTERNAL Py%(typename)s_Type = {\n'
  97.         '    PyObject_HEAD_INIT(NULL)\n'
  98.         '    0,                                 /* ob_size */\n'
  99.         '    "%(classname)s",                   /* tp_name */\n'
  100.         '    sizeof(%(tp_basicsize)s),          /* tp_basicsize */\n'
  101.         '    0,                                 /* tp_itemsize */\n'
  102.         '    /* methods */\n'
  103.         '    (destructor)%(tp_dealloc)s,        /* tp_dealloc */\n'
  104.         '    (printfunc)0,                      /* tp_print */\n'
  105.         '    (getattrfunc)%(tp_getattr)s,       /* tp_getattr */\n'
  106.         '    (setattrfunc)%(tp_setattr)s,       /* tp_setattr */\n'
  107.         '    (cmpfunc)%(tp_compare)s,           /* tp_compare */\n'
  108.         '    (reprfunc)%(tp_repr)s,             /* tp_repr */\n'
  109.         '    (PyNumberMethods*)%(tp_as_number)s,     /* tp_as_number */\n'
  110.         '    (PySequenceMethods*)%(tp_as_sequence)s, /* tp_as_sequence */\n'
  111.         '    (PyMappingMethods*)%(tp_as_mapping)s,   /* tp_as_mapping */\n'
  112.         '    (hashfunc)%(tp_hash)s,             /* tp_hash */\n'
  113.         '    (ternaryfunc)%(tp_call)s,          /* tp_call */\n'
  114.         '    (reprfunc)%(tp_str)s,              /* tp_str */\n'
  115.         '    (getattrofunc)%(tp_getattro)s,     /* tp_getattro */\n'
  116.         '    (setattrofunc)%(tp_setattro)s,     /* tp_setattro */\n'
  117.         '    (PyBufferProcs*)%(tp_as_buffer)s,  /* tp_as_buffer */\n'
  118.         '    %(tp_flags)s,                      /* tp_flags */\n'
  119.         '    %(tp_doc)s,                        /* Documentation string */\n'
  120.         '    (traverseproc)%(tp_traverse)s,     /* tp_traverse */\n'
  121.         '    (inquiry)%(tp_clear)s,             /* tp_clear */\n'
  122.         '    (richcmpfunc)%(tp_richcompare)s,   /* tp_richcompare */\n'
  123.         '    %(tp_weaklistoffset)s,             /* tp_weaklistoffset */\n'
  124.         '    (getiterfunc)%(tp_iter)s,          /* tp_iter */\n'
  125.         '    (iternextfunc)%(tp_iternext)s,     /* tp_iternext */\n'
  126.         '    (struct PyMethodDef*)%(tp_methods)s, /* tp_methods */\n'
  127.         '    (struct PyMemberDef*)0,              /* tp_members */\n'
  128.         '    (struct PyGetSetDef*)%(tp_getset)s,  /* tp_getset */\n'
  129.         '    NULL,                              /* tp_base */\n'
  130.         '    NULL,                              /* tp_dict */\n'
  131.         '    (descrgetfunc)%(tp_descr_get)s,    /* tp_descr_get */\n'
  132.         '    (descrsetfunc)%(tp_descr_set)s,    /* tp_descr_set */\n'
  133.         '    %(tp_dictoffset)s,                 /* tp_dictoffset */\n'
  134.         '    (initproc)%(tp_init)s,             /* tp_init */\n'
  135.         '    (allocfunc)%(tp_alloc)s,           /* tp_alloc */\n'
  136.         '    (newfunc)%(tp_new)s,               /* tp_new */\n'
  137.         '    (freefunc)%(tp_free)s,             /* tp_free */\n'
  138.         '    (inquiry)%(tp_is_gc)s              /* tp_is_gc */\n'
  139.         '};\n\n'
  140.         )
  141.  
  142.     slots_list = [
  143.         'tp_getattr', 'tp_setattr', 'tp_getattro', 'tp_setattro',
  144.         'tp_compare', 'tp_repr',
  145.         'tp_as_number', 'tp_as_sequence', 'tp_as_mapping', 'tp_hash',
  146.         'tp_call', 'tp_str', 'tp_as_buffer', 'tp_richcompare', 'tp_iter',
  147.         'tp_iternext', 'tp_descr_get', 'tp_descr_set', 'tp_init',
  148.         'tp_alloc', 'tp_new', 'tp_free', 'tp_is_gc',
  149.         'tp_traverse', 'tp_clear', 'tp_dealloc', 'tp_flags', 'tp_doc'
  150.         ]
  151.  
  152.     getter_tmpl = (
  153.         'static PyObject *\n'
  154.         '%(funcname)s(PyObject *self, void *closure)\n'
  155.         '{\n'
  156.         '%(varlist)s'
  157.         '    ret = %(field)s;\n'
  158.         '%(codeafter)s\n'
  159.         '}\n\n'
  160.         )
  161.  
  162.     parse_tmpl = (
  163.         '    if (!PyArg_ParseTupleAndKeywords(args, kwargs,'
  164.         '"%(typecodes)s:%(name)s"%(parselist)s))\n'
  165.         '        return %(errorreturn)s;\n'
  166.         )
  167.  
  168.     deprecated_tmpl = (
  169.         '    if (PyErr_Warn(PyExc_DeprecationWarning, '
  170.         '"%(deprecationmsg)s") < 0)\n'
  171.         '        return %(errorreturn)s;\n'
  172.         )
  173.  
  174.     methdef_tmpl = (
  175.         '    { "%(name)s", (PyCFunction)%(cname)s, %(flags)s,\n'
  176.         '      %(docstring)s },\n'
  177.         )
  178.  
  179.     noconstructor = (
  180.         'static int\n'
  181.         'pygobject_no_constructor(PyObject *self, PyObject *args, '
  182.         'PyObject *kwargs)\n'
  183.         '{\n'
  184.         '    gchar buf[512];\n'
  185.         '\n'
  186.         '    g_snprintf(buf, sizeof(buf), "%s is an abstract widget", '
  187.         'self->ob_type->tp_name);\n'
  188.         '    PyErr_SetString(PyExc_NotImplementedError, buf);\n'
  189.         '    return -1;\n'
  190.         '}\n\n'
  191.         )
  192.  
  193.     function_tmpl = (
  194.         'static PyObject *\n'
  195.         '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n'
  196.         '{\n'
  197.         '%(varlist)s'
  198.         '%(parseargs)s'
  199.         '%(codebefore)s'
  200.         '    %(begin_allow_threads)s\n'
  201.         '    %(setreturn)s%(cname)s(%(arglist)s);\n'
  202.         '    %(end_allow_threads)s\n'
  203.         '%(codeafter)s\n'
  204.         '}\n\n'
  205.         )
  206.  
  207.     virtual_accessor_tmpl = (
  208.         'static PyObject *\n'
  209.         '_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n'
  210.         '{\n'
  211.         '    gpointer klass;\n'
  212.         '%(varlist)s'
  213.         '%(parseargs)s'
  214.         '%(codebefore)s'
  215.         '    klass = g_type_class_ref(pyg_type_from_object(cls));\n'
  216.         '    if (%(class_cast_macro)s(klass)->%(virtual)s)\n'
  217.         '        %(setreturn)s%(class_cast_macro)s(klass)->'
  218.         '%(virtual)s(%(arglist)s);\n'
  219.         '    else {\n'
  220.         '        PyErr_SetString(PyExc_NotImplementedError, '
  221.         '"virtual method %(name)s not implemented");\n'
  222.         '        g_type_class_unref(klass);\n'
  223.         '        return NULL;\n'
  224.         '    }\n'
  225.         '    g_type_class_unref(klass);\n'
  226.         '%(codeafter)s\n'
  227.         '}\n\n'
  228.         )
  229.  
  230.     # template for method calls
  231.     constructor_tmpl = None
  232.     method_tmpl = None
  233.  
  234.     def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)):
  235.         self.parser = parser
  236.         self.objinfo = objinfo
  237.         self.overrides = overrides
  238.         self.fp = fp
  239.  
  240.     def get_lower_name(self):
  241.         return string.lower(string.replace(self.objinfo.typecode,
  242.                                            '_TYPE_', '_', 1))
  243.  
  244.     def get_field_accessor(self, fieldname):
  245.         raise NotImplementedError
  246.  
  247.     def get_initial_class_substdict(self): return {}
  248.  
  249.     def get_initial_constructor_substdict(self, constructor):
  250.         return { 'name': '%s.__init__' % self.objinfo.c_name,
  251.                  'errorreturn': '-1' }
  252.     def get_initial_method_substdict(self, method):
  253.         substdict = { 'name': '%s.%s' % (self.objinfo.c_name, method.name) }
  254.         if method.unblock_threads:
  255.             substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;'
  256.             substdict['end_allow_threads'] = 'pyg_end_allow_threads;'
  257.         else:
  258.             substdict['begin_allow_threads'] = ''
  259.             substdict['end_allow_threads'] = ''
  260.         return substdict
  261.  
  262.     def write_class(self):
  263.         if self.overrides.is_type_ignored(self.objinfo.c_name):
  264.             return
  265.         self.fp.write('\n/* ----------- %s ----------- */\n\n' %
  266.                       self.objinfo.c_name)
  267.         substdict = self.get_initial_class_substdict()
  268.         if not substdict.has_key('tp_flags'):
  269.             substdict['tp_flags'] = 'Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE'
  270.         substdict['typename'] = self.objinfo.c_name
  271.         if self.overrides.modulename:
  272.             substdict['classname'] = '%s.%s' % (self.overrides.modulename,
  273.                                            self.objinfo.name)
  274.         else:
  275.             substdict['classname'] = self.objinfo.name
  276.         substdict['tp_doc'] = self.objinfo.docstring
  277.  
  278.         # Maybe this could be done in a nicer way, but I'll leave it as it is
  279.         # for now: -- Johan
  280.         if not self.overrides.slot_is_overriden('%s.tp_init' %
  281.                                                 self.objinfo.c_name):
  282.             substdict['tp_init'] = self.write_constructor()
  283.         substdict['tp_methods'] = self.write_methods()
  284.         substdict['tp_getset'] = self.write_getsets()
  285.  
  286.         # handle slots ...
  287.         for slot in self.slots_list:
  288.  
  289.             slotname = '%s.%s' % (self.objinfo.c_name, slot)
  290.             slotfunc = '_wrap_%s_%s' % (self.get_lower_name(), slot)
  291.             if slot[:6] == 'tp_as_':
  292.                 slotfunc = '&' + slotfunc
  293.             if self.overrides.slot_is_overriden(slotname):
  294.                 data = self.overrides.slot_override(slotname)
  295.                 self.write_function(slotname, data)
  296.                 substdict[slot] = slotfunc
  297.             else:
  298.                 if not substdict.has_key(slot):
  299.                     substdict[slot] = '0'
  300.  
  301.         self.fp.write(self.type_tmpl % substdict)
  302.  
  303.         self.write_virtuals()
  304.  
  305.     def write_function_wrapper(self, function_obj, template,
  306.                                handle_return=0, is_method=0, kwargs_needed=0,
  307.                                substdict=None):
  308.         '''This function is the guts of all functions that generate
  309.         wrappers for functions, methods and constructors.'''
  310.         if not substdict: substdict = {}
  311.  
  312.         info = argtypes.WrapperInfo()
  313.  
  314.         substdict.setdefault('errorreturn', 'NULL')
  315.  
  316.         # for methods, we want the leading comma
  317.         if is_method:
  318.             info.arglist.append('')
  319.  
  320.         if function_obj.varargs:
  321.             raise argtypes.ArgTypeNotFoundError("varargs functions not supported")
  322.  
  323.         for param in function_obj.params:
  324.             if param.pdflt != None and '|' not in info.parsestr:
  325.                 info.add_parselist('|', [], [])
  326.             handler = argtypes.matcher.get(param.ptype)
  327.             handler.write_param(param.ptype, param.pname, param.pdflt,
  328.                                 param.pnull, info)
  329.  
  330.         substdict['setreturn'] = ''
  331.         if handle_return:
  332.             if function_obj.ret not in ('none', None):
  333.                 substdict['setreturn'] = 'ret = '
  334.             handler = argtypes.matcher.get(function_obj.ret)
  335.             handler.write_return(function_obj.ret,
  336.                                  function_obj.caller_owns_return, info)
  337.  
  338.         if function_obj.deprecated != None:
  339.             deprecated = self.deprecated_tmpl % {
  340.                 'deprecationmsg': function_obj.deprecated,
  341.                 'errorreturn': substdict['errorreturn'] }
  342.         else:
  343.             deprecated = ''
  344.  
  345.         # if name isn't set, set it to function_obj.name
  346.         substdict.setdefault('name', function_obj.name)
  347.  
  348.         if function_obj.unblock_threads:
  349.             substdict['begin_allow_threads'] = 'pyg_begin_allow_threads;'
  350.             substdict['end_allow_threads'] = 'pyg_end_allow_threads;'
  351.         else:
  352.             substdict['begin_allow_threads'] = ''
  353.             substdict['end_allow_threads'] = ''
  354.  
  355.         if self.objinfo:
  356.             substdict['typename'] = self.objinfo.c_name
  357.         substdict.setdefault('cname',  function_obj.c_name)
  358.         substdict['varlist'] = info.get_varlist()
  359.         substdict['typecodes'] = info.parsestr
  360.         substdict['parselist'] = info.get_parselist()
  361.         substdict['arglist'] = info.get_arglist()
  362.         substdict['codebefore'] = deprecated + (
  363.             string.replace(info.get_codebefore(),
  364.             'return NULL', 'return ' + substdict['errorreturn'])
  365.             )
  366.         substdict['codeafter'] = (
  367.             string.replace(info.get_codeafter(),
  368.                            'return NULL',
  369.                            'return ' + substdict['errorreturn']))
  370.  
  371.         if info.parsestr or kwargs_needed:
  372.             substdict['parseargs'] = self.parse_tmpl % substdict
  373.             substdict['extraparams'] = ', PyObject *args, PyObject *kwargs'
  374.             flags = 'METH_VARARGS|METH_KEYWORDS'
  375.  
  376.             # prepend the keyword list to the variable list
  377.             substdict['varlist'] = info.get_kwlist() + substdict['varlist']
  378.         else:
  379.             substdict['parseargs'] = ''
  380.             substdict['extraparams'] = ''
  381.             flags = 'METH_NOARGS'
  382.  
  383.         return template % substdict, flags
  384.  
  385.     def write_constructor(self):
  386.         initfunc = '0'
  387.         constructor = self.parser.find_constructor(self.objinfo,self.overrides)
  388.         if not constructor:
  389.             return self.write_default_constructor()
  390.  
  391.         funcname = constructor.c_name
  392.         try:
  393.             if self.overrides.is_overriden(funcname):
  394.                 data = self.overrides.override(funcname)
  395.                 self.write_function(funcname, data)
  396.                 self.objinfo.has_new_constructor_api = (
  397.                     self.objinfo.typecode in
  398.                     self.overrides.newstyle_constructors)
  399.             else:
  400.                 # ok, a hack to determine if we should use
  401.                 # new-style constructores :P
  402.                 property_based = getattr(self,
  403.                                          'write_property_based_constructor',
  404.                                          None)
  405.                 if property_based:
  406.                     if (len(constructor.params) == 0 or
  407.                         isinstance(constructor.params[0],
  408.                                    definitions.Property)):
  409.                         # write_property_based_constructor is only
  410.                         # implemented in GObjectWrapper
  411.                         return self.write_property_based_constructor(
  412.                             constructor)
  413.                     else:
  414.                         sys.stderr.write(
  415.                             "Warning: generating old-style constructor for:" +
  416.                             constructor.c_name + '\n')
  417.  
  418.                 # write constructor from template ...
  419.                 code = self.write_function_wrapper(constructor,
  420.                     self.constructor_tmpl,
  421.                     handle_return=0, is_method=0, kwargs_needed=1,
  422.                     substdict=self.get_initial_constructor_substdict(
  423.                     constructor))[0]
  424.                 self.fp.write(code)
  425.             initfunc = '_wrap_' + funcname
  426.         except argtypes.ArgTypeError, ex:
  427.             sys.stderr.write('Could not write constructor for %s: %s\n'
  428.                              % (self.objinfo.c_name, str(ex)))
  429.  
  430.             initfunc = self.write_noconstructor()
  431.         return initfunc
  432.  
  433.     def write_noconstructor(self):
  434.         # this is a hack ...
  435.         if not hasattr(self.overrides, 'no_constructor_written'):
  436.             self.fp.write(self.noconstructor)
  437.             self.overrides.no_constructor_written = 1
  438.         initfunc = 'pygobject_no_constructor'
  439.         return initfunc
  440.  
  441.     def write_default_constructor(self):
  442.         return self.write_noconstructor()
  443.  
  444.     def get_methflags(self, funcname):
  445.         if self.overrides.wants_kwargs(funcname):
  446.             flags = 'METH_VARARGS|METH_KEYWORDS'
  447.         elif self.overrides.wants_noargs(funcname):
  448.             flags = 'METH_NOARGS'
  449.         elif self.overrides.wants_onearg(funcname):
  450.             flags = 'METH_O'
  451.         else:
  452.             flags = 'METH_VARARGS'
  453.         if self.overrides.is_staticmethod(funcname):
  454.             flags += '|METH_STATIC'
  455.         elif self.overrides.is_classmethod(funcname):
  456.             flags += '|METH_CLASS'
  457.         return flags
  458.  
  459.     def write_function(self, funcname, data):
  460.         lineno, filename = self.overrides.getstartline(funcname)
  461.         self.fp.setline(lineno, filename)
  462.         self.fp.write(data)
  463.         self.fp.resetline()
  464.         self.fp.write('\n\n')
  465.  
  466.     def _get_class_virtual_substdict(self, meth, cname, parent):
  467.         substdict = self.get_initial_method_substdict(meth)
  468.         substdict['virtual'] = substdict['name'].split('.')[1]
  469.         substdict['cname'] = cname
  470.         substdict['class_cast_macro'] = parent.typecode.replace(
  471.             '_TYPE_', '_', 1) + "_CLASS"
  472.         substdict['typecode'] = self.objinfo.typecode
  473.         substdict['cast'] = string.replace(parent.typecode, '_TYPE_', '_', 1)
  474.         return substdict
  475.  
  476.     def write_methods(self):
  477.         methods = []
  478.         klass = self.objinfo.c_name
  479.         # First, get methods from the defs files
  480.         for meth in self.parser.find_methods(self.objinfo):
  481.             method_name = meth.c_name
  482.             if self.overrides.is_ignored(method_name):
  483.                 continue
  484.             try:
  485.                 if self.overrides.is_overriden(method_name):
  486.                     if not self.overrides.is_already_included(method_name):
  487.                         data = self.overrides.override(method_name)
  488.                         self.write_function(method_name, data)
  489.  
  490.                     methflags = self.get_methflags(method_name)
  491.                 else:
  492.                     # write constructor from template ...
  493.                     code, methflags = self.write_function_wrapper(meth,
  494.                         self.method_tmpl, handle_return=1, is_method=1,
  495.                         substdict=self.get_initial_method_substdict(meth))
  496.                     self.fp.write(code)
  497.                 methods.append(self.methdef_tmpl %
  498.                                { 'name':  fixname(meth.name),
  499.                                  'cname': '_wrap_' + method_name,
  500.                                  'flags': methflags,
  501.                                  'docstring': meth.docstring })
  502.                 methods_coverage.declare_wrapped()
  503.             except argtypes.ArgTypeError, ex:
  504.                 methods_coverage.declare_not_wrapped()
  505.                 sys.stderr.write('Could not write method %s.%s: %s\n'
  506.                                 % (klass, meth.name, str(ex)))
  507.  
  508.         # Now try to see if there are any defined in the override
  509.         for method_name in self.overrides.get_defines_for(klass):
  510.             c_name = override.class2cname(klass, method_name)
  511.             if self.overrides.is_already_included(method_name):
  512.                 continue
  513.  
  514.             try:
  515.                 data = self.overrides.define(klass, method_name)
  516.                 self.write_function(method_name, data)
  517.                 methflags = self.get_methflags(method_name)
  518.  
  519.                 methods.append(self.methdef_tmpl %
  520.                                { 'name':  method_name,
  521.                                  'cname': '_wrap_' + c_name,
  522.                                  'flags': methflags,
  523.                                  'docstring': 'NULL' })
  524.                 methods_coverage.declare_wrapped()
  525.             except argtypes.ArgTypeError, ex:
  526.                 methods_coverage.declare_not_wrapped()
  527.                 sys.stderr.write('Could not write method %s.%s: %s\n'
  528.                                 % (klass, method_name, str(ex)))
  529.  
  530.         # Add GObject virtual method accessors, for chaining to parent
  531.         # virtuals from subclasses
  532.         methods += self.write_virtual_accessors()
  533.  
  534.         if methods:
  535.             methoddefs = '_Py%s_methods' % self.objinfo.c_name
  536.             # write the PyMethodDef structure
  537.             methods.append('    { NULL, NULL, 0, NULL }\n')
  538.             self.fp.write('static const PyMethodDef %s[] = {\n' % methoddefs)
  539.             self.fp.write(string.join(methods, ''))
  540.             self.fp.write('};\n\n')
  541.         else:
  542.             methoddefs = 'NULL'
  543.         return methoddefs
  544.  
  545.     def write_virtual_accessors(self):
  546.         klass = self.objinfo.c_name
  547.         methods = []
  548.         for meth in self.parser.find_virtuals(self.objinfo):
  549.             method_name = self.objinfo.c_name + "__do_" + meth.name
  550.             if self.overrides.is_ignored(method_name):
  551.                 continue
  552.             try:
  553.                 if self.overrides.is_overriden(method_name):
  554.                     if not self.overrides.is_already_included(method_name):
  555.                         data = self.overrides.override(method_name)
  556.                         self.write_function(method_name, data)
  557.                     methflags = self.get_methflags(method_name)
  558.                 else:
  559.                     # temporarily add a 'self' parameter as first argument
  560.                     meth.params.insert(0, definitions.Parameter(
  561.                         ptype=(self.objinfo.c_name + '*'),
  562.                         pname='self', pdflt=None, pnull=None))
  563.                     try:
  564.                         # write method from template ...
  565.                         code, methflags = self.write_function_wrapper(
  566.                             meth, self.virtual_accessor_tmpl,
  567.                             handle_return=True, is_method=False,
  568.                             substdict=self._get_class_virtual_substdict(
  569.                             meth, method_name, self.objinfo))
  570.                         self.fp.write(code)
  571.                     finally:
  572.                         del meth.params[0]
  573.                 methods.append(self.methdef_tmpl %
  574.                                { 'name':  "do_" + fixname(meth.name),
  575.                                  'cname': '_wrap_' + method_name,
  576.                                  'flags': methflags + '|METH_CLASS',
  577.                                  'docstring': 'NULL'})
  578.                 vaccessors_coverage.declare_wrapped()
  579.             except argtypes.ArgTypeError, ex:
  580.                 vaccessors_coverage.declare_not_wrapped()
  581.                 sys.stderr.write(
  582.                     'Could not write virtual accessor method %s.%s: %s\n'
  583.                     % (klass, meth.name, str(ex)))
  584.         return methods
  585.  
  586.     def write_virtuals(self):
  587.         '''
  588.         Write _wrap_FooBar__proxy_do_zbr() reverse wrapers for
  589.         GObject virtuals
  590.         '''
  591.         klass = self.objinfo.c_name
  592.         virtuals = []
  593.         for meth in self.parser.find_virtuals(self.objinfo):
  594.             method_name = self.objinfo.c_name + "__proxy_do_" + meth.name
  595.             if self.overrides.is_ignored(method_name):
  596.                 continue
  597.             try:
  598.                 if self.overrides.is_overriden(method_name):
  599.                     if not self.overrides.is_already_included(method_name):
  600.                         data = self.overrides.override(method_name)
  601.                         self.write_function(method_name, data)
  602.                 else:
  603.                     # write virtual proxy ...
  604.                     ret, props = argtypes.matcher.get_reverse_ret(meth.ret)
  605.                     wrapper = reversewrapper.ReverseWrapper(
  606.                         '_wrap_' + method_name, is_static=True)
  607.                     wrapper.set_return_type(ret(wrapper, **props))
  608.                     wrapper.add_parameter(reversewrapper.PyGObjectMethodParam(
  609.                         wrapper, "self", method_name="do_" + meth.name,
  610.                         c_type=(klass + ' *')))
  611.                     for param in meth.params:
  612.                         handler, props = argtypes.matcher.get_reverse(
  613.                             param.ptype)
  614.                         props["direction"] = param.pdir
  615.                         wrapper.add_parameter(handler(wrapper,
  616.                                                       param.pname, **props))
  617.                     buf = reversewrapper.MemoryCodeSink()
  618.                     wrapper.generate(buf)
  619.                     self.fp.write(buf.flush())
  620.                 virtuals.append((fixname(meth.name), '_wrap_' + method_name))
  621.                 vproxies_coverage.declare_wrapped()
  622.             except argtypes.ArgTypeError, ex:
  623.                 vproxies_coverage.declare_not_wrapped()
  624.                 virtuals.append((fixname(meth.name), None))
  625.                 sys.stderr.write('Could not write virtual proxy %s.%s: %s\n'
  626.                                 % (klass, meth.name, str(ex)))
  627.         if virtuals:
  628.             # Write a 'pygtk class init' function for this object,
  629.             # except when the object type is explicitly ignored (like
  630.             # GtkPlug and GtkSocket on win32).
  631.             if self.overrides.is_ignored(self.objinfo.typecode):
  632.                 return
  633.             class_cast_macro = self.objinfo.typecode.replace(
  634.                 '_TYPE_', '_', 1) + "_CLASS"
  635.             cast_macro = self.objinfo.typecode.replace('_TYPE_', '_', 1)
  636.             funcname = "__%s_class_init" % klass
  637.             self.objinfo.class_init_func = funcname
  638.             have_implemented_virtuals = not not [True
  639.                                                  for name, cname in virtuals
  640.                                                      if cname is not None]
  641.             self.fp.write(
  642.             ('\nstatic int\n'
  643.              '%(funcname)s(gpointer gclass, PyTypeObject *pyclass)\n'
  644.              '{\n') % vars())
  645.  
  646.             if have_implemented_virtuals:
  647.                 self.fp.write('    PyObject *o;\n')
  648.                 self.fp.write(
  649.                     '    %(klass)sClass *klass = '
  650.                     '%(class_cast_macro)s(gclass);\n'
  651.                     '    PyObject *gsignals = '
  652.                     'PyDict_GetItemString(pyclass->tp_dict, "__gsignals__");\n'
  653.                     % vars())
  654.  
  655.             for name, cname in virtuals:
  656.                 do_name = 'do_' + name
  657.                 if cname is None:
  658.                     self.fp.write('\n    /* overriding %(do_name)s '
  659.                                   'is currently not supported */\n' % vars())
  660.                 else:
  661.                     self.fp.write('''
  662.     o = PyObject_GetAttrString((PyObject *) pyclass, "%(do_name)s");
  663.     if (o == NULL)
  664.         PyErr_Clear();
  665.     else {
  666.         if (!PyObject_TypeCheck(o, &PyCFunction_Type)
  667.             && !(gsignals && PyDict_GetItemString(gsignals, "%(name)s")))
  668.             klass->%(name)s = %(cname)s;
  669.         Py_DECREF(o);
  670.     }
  671. ''' % vars())
  672.             self.fp.write('    return 0;\n}\n')
  673.  
  674.     def write_getsets(self):
  675.         lower_name = self.get_lower_name()
  676.         getsets_name = lower_name + '_getsets'
  677.         getterprefix = '_wrap_' + lower_name + '__get_'
  678.         setterprefix = '_wrap_' + lower_name + '__set_'
  679.  
  680.         # no overrides for the whole function.  If no fields,
  681.         # don't write a func
  682.         if not self.objinfo.fields:
  683.             return '0'
  684.         getsets = []
  685.         for ftype, cfname in self.objinfo.fields:
  686.             fname = cfname.replace('.', '_')
  687.             gettername = '0'
  688.             settername = '0'
  689.             attrname = self.objinfo.c_name + '.' + fname
  690.             if self.overrides.attr_is_overriden(attrname):
  691.                 code = self.overrides.attr_override(attrname)
  692.                 self.write_function(attrname, code)
  693.                 if string.find(code, getterprefix + fname) >= 0:
  694.                     gettername = getterprefix + fname
  695.                 if string.find(code, setterprefix + fname) >= 0:
  696.                     settername = setterprefix + fname
  697.             if gettername == '0':
  698.                 try:
  699.                     funcname = getterprefix + fname
  700.                     info = argtypes.WrapperInfo()
  701.                     handler = argtypes.matcher.get(ftype)
  702.                     # for attributes, we don't own the "return value"
  703.                     handler.write_return(ftype, 0, info)
  704.                     self.fp.write(self.getter_tmpl %
  705.                                   { 'funcname': funcname,
  706.                                     'varlist': info.varlist,
  707.                                     'field': self.get_field_accessor(cfname),
  708.                                     'codeafter': info.get_codeafter() })
  709.                     gettername = funcname
  710.                 except argtypes.ArgTypeError, ex:
  711.                     sys.stderr.write(
  712.                         "Could not write getter for %s.%s: %s\n"
  713.                         % (self.objinfo.c_name, fname, str(ex)))
  714.             if gettername != '0' or settername != '0':
  715.                 getsets.append('    { "%s", (getter)%s, (setter)%s },\n' %
  716.                                (fixname(fname), gettername, settername))
  717.  
  718.         if not getsets:
  719.             return '0'
  720.         self.fp.write('static const PyGetSetDef %s[] = {\n' % getsets_name)
  721.         for getset in getsets:
  722.             self.fp.write(getset)
  723.         self.fp.write('    { NULL, (getter)0, (setter)0 },\n')
  724.         self.fp.write('};\n\n')
  725.  
  726.         return getsets_name
  727.  
  728.     def _write_get_symbol_names(self, writer, functions):
  729.         self.fp.write("""static PyObject *
  730. _wrap__get_symbol_names(PyObject *self)
  731. {
  732.     PyObject *pylist = PyList_New(0);
  733.  
  734. """)
  735.         for obj, bases in writer.get_classes():
  736.             self.fp.write('    PyList_Append(pylist, '
  737.                           'PyString_FromString("%s"));\n' % (obj.name))
  738.  
  739.         for name, cname, flags, docstring in functions:
  740.             self.fp.write('    PyList_Append(pylist, '
  741.                           'PyString_FromString("%s"));\n' % (name))
  742.  
  743.         for enum in writer.get_enums():
  744.             self.fp.write('    PyList_Append(pylist, '
  745.                           'PyString_FromString("%s"));\n' % (enum.name))
  746.             for nick, value in enum.values:
  747.                 name = value[len(self.overrides.modulename)+1:]
  748.                 self.fp.write('    PyList_Append(pylist, '
  749.                               'PyString_FromString("%s"));\n' % (name))
  750.  
  751.         self.fp.write("    return pylist;\n}\n\n");
  752.  
  753.     def _write_get_symbol(self, writer, functions):
  754.         self.fp.write("""static PyObject *
  755. _wrap__get_symbol(PyObject *self, PyObject *args)
  756. {
  757.     PyObject *d;
  758.     char *name;
  759.     static PyObject *modulename = NULL;
  760.     static PyObject *module = NULL;
  761.     static char *strip_prefix = "%s";
  762.  
  763.     if (!PyArg_ParseTuple(args, "Os", &d, &name))
  764.         return NULL;
  765.  
  766.     if (!modulename)
  767.        modulename = PyString_FromString("%s");
  768.  
  769.     if (!module)
  770.        module = PyDict_GetItemString(d, "__module__");
  771.  
  772. """ % (self.overrides.modulename.upper() + '_',
  773.        self.overrides.modulename))
  774.  
  775.         first = True
  776.         # Classes / GObjects
  777.         for obj, bases in writer.get_classes():
  778.             if first:
  779.                 self.fp.write('    if (!strcmp(name, "%s")) {\n' % obj.name)
  780.                 first = False
  781.             else:
  782.                 self.fp.write('    } else if (!strcmp(name, "%s")) {\n' % obj.name)
  783.             self.fp.write(
  784.                 '       return (PyObject*)pygobject_lookup_class(%s);\n' %
  785.                 obj.typecode)
  786.         self.fp.write('    }\n')
  787.  
  788.         # Functions
  789.         for name, cname, flags, docstring in functions:
  790.             self.fp.write('    else if (!strcmp(name, "%s")) {\n' % name)
  791.             self.fp.write('        static PyMethodDef ml = { '
  792.                           '"%s", (PyCFunction)%s, %s, "%s"};\n' % (
  793.                 name, cname, flags, docstring))
  794.             self.fp.write('        return PyCFunction_NewEx(&ml, NULL, modulename);\n')
  795.             self.fp.write('    }\n')
  796.  
  797.         # Enums
  798.         def write_enum(enum, returnobj=False):
  799.             if returnobj:
  800.                 ret = 'return '
  801.             else:
  802.                 ret = ''
  803.             if enum.deftype == 'enum':
  804.                 self.fp.write(
  805.                     '        %spyg_enum_add(module, "%s", strip_prefix, %s);\n'
  806.                     % (ret, enum.name, enum.typecode))
  807.             else:
  808.                 self.fp.write(
  809.                     '    %spyg_flags_add(module, "%s", strip_prefix, %s);\n'
  810.                     % (ret, enum.name, enum.typecode))
  811.  
  812.         strip_len = len(self.overrides.modulename)+1 # GTK_
  813.         for enum in writer.get_enums():
  814.             # XXX: Implement without typecodes
  815.             self.fp.write('    else if (!strcmp(name, "%s")) {\n' % enum.name)
  816.             write_enum(enum, returnobj=True)
  817.             self.fp.write('    }\n')
  818.  
  819.             for nick, value in enum.values:
  820.                 value = value[strip_len:]
  821.                 self.fp.write('    else if (!strcmp(name, "%s")) {\n' % value)
  822.                 write_enum(enum)
  823.                 self.fp.write('        return PyObject_GetAttrString(module, "%s");\n' %
  824.                               value)
  825.                 self.fp.write('    }\n')
  826.  
  827.         self.fp.write('    return Py_None;\n}\n\n');
  828.  
  829.     def _write_function_bodies(self):
  830.         functions = []
  831.         # First, get methods from the defs files
  832.         for func in self.parser.find_functions():
  833.             funcname = func.c_name
  834.             if self.overrides.is_ignored(funcname):
  835.                 continue
  836.             try:
  837.                 if self.overrides.is_overriden(funcname):
  838.                     data = self.overrides.override(funcname)
  839.                     self.write_function(funcname, data)
  840.  
  841.                     methflags = self.get_methflags(funcname)
  842.                 else:
  843.                     # write constructor from template ...
  844.                     code, methflags = self.write_function_wrapper(func,
  845.                         self.function_tmpl, handle_return=1, is_method=0)
  846.                     self.fp.write(code)
  847.                 functions.append((func.name, '_wrap_' + funcname,
  848.                                   methflags, func.docstring))
  849.                 functions_coverage.declare_wrapped()
  850.             except argtypes.ArgTypeError, ex:
  851.                 functions_coverage.declare_not_wrapped()
  852.                 sys.stderr.write('Could not write function %s: %s\n'
  853.                                  % (func.name, str(ex)))
  854.  
  855.         # Now try to see if there are any defined in the override
  856.         for funcname in self.overrides.get_functions():
  857.             try:
  858.                 data = self.overrides.function(funcname)
  859.                 self.write_function(funcname, data)
  860.                 methflags = self.get_methflags(funcname)
  861.                 functions.append((funcname, '_wrap_' + funcname,
  862.                                   methflags, 'NULL'))
  863.                 functions_coverage.declare_wrapped()
  864.             except argtypes.ArgTypeError, ex:
  865.                 functions_coverage.declare_not_wrapped()
  866.                 sys.stderr.write('Could not write function %s: %s\n'
  867.                                  % (funcname, str(ex)))
  868.         return functions
  869.  
  870.     def write_functions(self, writer, prefix):
  871.         self.fp.write('\n/* ----------- functions ----------- */\n\n')
  872.         functions = []
  873.         func_infos = self._write_function_bodies()
  874.  
  875.         # If we have a dynamic namespace, write symbol and attribute getter
  876.         if self.overrides.dynamicnamespace:
  877.             self._write_get_symbol_names(writer, func_infos)
  878.             self._write_get_symbol(writer, func_infos)
  879.             for obj, bases in writer.get_classes():
  880.                 self.fp.write("""static PyTypeObject *
  881. %s_register_type(const gchar *name, PyObject *unused)
  882. {
  883.     PyObject *m = PyImport_ImportModule("gtk");
  884.     PyObject *d = PyModule_GetDict(m);
  885. """ % obj.c_name)
  886.                 writer.write_class(obj, bases, indent=1)
  887.                 self.fp.write(
  888.                     '    return (%s)PyDict_GetItemString(d, "%s");\n' % (
  889.                     'PyTypeObject*', obj.name))
  890.                 self.fp.write("}\n")
  891.  
  892.             functions.append('    { "_get_symbol_names", '
  893.                              '(PyCFunction)_wrap__get_symbol_names, '
  894.                              'METH_NOARGS, NULL },\n')
  895.             functions.append('    { "_get_symbol", '
  896.                              '(PyCFunction)_wrap__get_symbol, '
  897.                              'METH_VARARGS, NULL },\n')
  898.         else:
  899.             for name, cname, flags, docstring in func_infos:
  900.                 functions.append(self.methdef_tmpl % dict(name=name,
  901.                                                           cname=cname,
  902.                                                           flags=flags,
  903.                                                           docstring=docstring))
  904.  
  905.         # write the PyMethodDef structure
  906.         functions.append('    { NULL, NULL, 0, NULL }\n')
  907.  
  908.         self.fp.write('const PyMethodDef ' + prefix + '_functions[] = {\n')
  909.         self.fp.write(string.join(functions, ''))
  910.         self.fp.write('};\n\n')
  911.  
  912. class GObjectWrapper(Wrapper):
  913.     constructor_tmpl = (
  914.         'static int\n'
  915.         '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n'
  916.         '{\n'
  917.         '%(varlist)s'
  918.         '%(parseargs)s'
  919.         '%(codebefore)s'
  920.         '    self->obj = (GObject *)%(cname)s(%(arglist)s);\n'
  921.         '%(codeafter)s\n'
  922.         '    if (!self->obj) {\n'
  923.         '        PyErr_SetString(PyExc_RuntimeError, '
  924.         '"could not create %(typename)s object");\n'
  925.         '        return -1;\n'
  926.         '    }\n'
  927.         '%(aftercreate)s'
  928.         '    pygobject_register_wrapper((PyObject *)self);\n'
  929.         '    return 0;\n'
  930.         '}\n\n'
  931.         )
  932.  
  933.     method_tmpl = (
  934.         'static PyObject *\n'
  935.         '_wrap_%(cname)s(PyGObject *self%(extraparams)s)\n'
  936.         '{\n'
  937.         '%(varlist)s'
  938.         '%(parseargs)s'
  939.         '%(codebefore)s'
  940.         '    %(begin_allow_threads)s\n'
  941.         '    %(setreturn)s%(cname)s(%(cast)s(self->obj)%(arglist)s);\n'
  942.         '    %(end_allow_threads)s\n'
  943.         '%(codeafter)s\n'
  944.         '}\n\n'
  945.         )
  946.     def __init__(self, parser, objinfo, overrides, fp=FileOutput(sys.stdout)):
  947.         Wrapper.__init__(self, parser, objinfo, overrides, fp)
  948.         if self.objinfo:
  949.             self.castmacro = string.replace(self.objinfo.typecode,
  950.                                             '_TYPE_', '_', 1)
  951.  
  952.     def get_initial_class_substdict(self):
  953.         return { 'tp_basicsize'      : 'PyGObject',
  954.                  'tp_weaklistoffset' : 'offsetof(PyGObject, weakreflist)',
  955.                  'tp_dictoffset'     : 'offsetof(PyGObject, inst_dict)' }
  956.  
  957.     def get_field_accessor(self, fieldname):
  958.         castmacro = string.replace(self.objinfo.typecode, '_TYPE_', '_', 1)
  959.         return '%s(pygobject_get(self))->%s' % (castmacro, fieldname)
  960.  
  961.     def get_initial_constructor_substdict(self, constructor):
  962.         substdict = Wrapper.get_initial_constructor_substdict(self,
  963.                                                               constructor)
  964.         if not constructor.caller_owns_return:
  965.             substdict['aftercreate'] = "    g_object_ref(self->obj);\n"
  966.         else:
  967.             substdict['aftercreate'] = ''
  968.         return substdict
  969.  
  970.     def get_initial_method_substdict(self, method):
  971.         substdict = Wrapper.get_initial_method_substdict(self, method)
  972.         substdict['cast'] = string.replace(self.objinfo.typecode,
  973.                                            '_TYPE_', '_', 1)
  974.         return substdict
  975.  
  976.     def write_default_constructor(self):
  977.         try:
  978.             parent = self.parser.find_object(self.objinfo.parent)
  979.         except ValueError:
  980.             parent = None
  981.         if parent is not None:
  982.             ## just like the constructor is inheritted, we should
  983.             # inherit the new API compatibility flag
  984.             self.objinfo.has_new_constructor_api = (
  985.                 parent.has_new_constructor_api)
  986.         elif self.objinfo.parent == 'GObject':
  987.             self.objinfo.has_new_constructor_api = True
  988.         return '0'
  989.  
  990.     def write_property_based_constructor(self, constructor):
  991.         self.objinfo.has_new_constructor_api = True
  992.         out = self.fp
  993.         print >> out, "static int"
  994.         print >> out, '_wrap_%s(PyGObject *self, PyObject *args,' \
  995.               ' PyObject *kwargs)\n{' % constructor.c_name
  996.         if constructor.params:
  997.             s = "    GType obj_type = pyg_type_from_object((PyObject *) self);"
  998.             print >> out, s
  999.  
  1000.         def py_str_list_to_c(arg):
  1001.             if arg:
  1002.                 return "{" + ", ".join(
  1003.                     map(lambda s: '"' + s + '"', arg)) + ", NULL }"
  1004.             else:
  1005.                 return "{ NULL }"
  1006.  
  1007.         classname = '%s.%s' % (self.overrides.modulename,
  1008.                                self.objinfo.name)
  1009.  
  1010.         if constructor.params:
  1011.             mandatory_arguments = [param for param in constructor.params
  1012.                                              if not param.optional]
  1013.             optional_arguments = [param for param in constructor.params
  1014.                                             if param.optional]
  1015.             arg_names = py_str_list_to_c(
  1016.             [param.argname
  1017.              for param in mandatory_arguments + optional_arguments])
  1018.  
  1019.             prop_names = py_str_list_to_c(
  1020.             [param.pname
  1021.              for param in mandatory_arguments + optional_arguments])
  1022.  
  1023.             print >> out, "    GParameter params[%i];" % \
  1024.                   len(constructor.params)
  1025.             print >> out, "    PyObject *parsed_args[%i] = {NULL, };" % \
  1026.                   len(constructor.params)
  1027.             print >> out, "    char *arg_names[] = %s;" % arg_names
  1028.             print >> out, "    char *prop_names[] = %s;" % prop_names
  1029.             print >> out, "    guint nparams, i;"
  1030.             print >> out
  1031.             if constructor.deprecated is not None:
  1032.                 out.write(
  1033.                     '    if (PyErr_Warn(PyExc_DeprecationWarning, '
  1034.                     '"%s") < 0)\n' %
  1035.                     constructor.deprecated)
  1036.                 print >> out, '        return -1;'
  1037.                 print >> out
  1038.             out.write("    if (!PyArg_ParseTupleAndKeywords(args, kwargs, ")
  1039.             template = '"'
  1040.             if mandatory_arguments:
  1041.                 template += "O"*len(mandatory_arguments)
  1042.             if optional_arguments:
  1043.                 template += "|" + "O"*len(optional_arguments)
  1044.             template += ':%s.__init__"' % classname
  1045.             print >> out, template, ", arg_names",
  1046.             for i in range(len(constructor.params)):
  1047.                 print >> out, ", &parsed_args[%i]" % i,
  1048.  
  1049.             out.write(
  1050.                 "))\n"
  1051.                 "        return -1;\n"
  1052.                 "\n"
  1053.                 "    memset(params, 0, sizeof(GParameter)*%i);\n"
  1054.                 "    if (!pyg_parse_constructor_args(obj_type, arg_names,\n"
  1055.                 "                                    prop_names, params, \n"
  1056.                 "                                    &nparams, parsed_args))\n"
  1057.                 "        return -1;\n"
  1058.                 "    pygobject_constructv(self, nparams, params);\n"
  1059.                 "    for (i = 0; i < nparams; ++i)\n"
  1060.                 "        g_value_unset(¶ms[i].value);\n"
  1061.                 % len(constructor.params))
  1062.         else:
  1063.             out.write(
  1064.                 "    static char* kwlist[] = { NULL };\n"
  1065.                 "\n")
  1066.  
  1067.             if constructor.deprecated is not None:
  1068.                 out.write(
  1069.                     '    if (PyErr_Warn(PyExc_DeprecationWarning, "%s") < 0)\n'
  1070.                     '        return -1;\n'
  1071.                     '\n' % constructor.deprecated)
  1072.  
  1073.             out.write(
  1074.                 '    if (!PyArg_ParseTupleAndKeywords(args, kwargs,\n'
  1075.                 '                                     ":%s.__init__",\n'
  1076.                 '                                     kwlist))\n'
  1077.                 '        return -1;\n'
  1078.                 '\n'
  1079.                 '    pygobject_constructv(self, 0, NULL);\n' % classname)
  1080.         out.write(
  1081.             '    if (!self->obj) {\n'
  1082.             '        PyErr_SetString(\n'
  1083.             '            PyExc_RuntimeError, \n'
  1084.             '            "could not create %s object");\n'
  1085.             '        return -1;\n'
  1086.             '    }\n' % classname)
  1087.  
  1088.         if not constructor.caller_owns_return:
  1089.             print >> out, "    g_object_ref(self->obj);\n"
  1090.  
  1091.         out.write(
  1092.             '    return 0;\n'
  1093.             '}\n\n')
  1094.  
  1095.         return "_wrap_%s" % constructor.c_name
  1096.  
  1097.  
  1098. class GInterfaceWrapper(GObjectWrapper):
  1099.     virtual_accessor_tmpl = (
  1100.         'static PyObject *\n'
  1101.         '_wrap_%(cname)s(PyObject *cls%(extraparams)s)\n'
  1102.         '{\n'
  1103.         '    %(vtable)s *iface;\n'
  1104.         '%(varlist)s'
  1105.         '%(parseargs)s'
  1106.         '%(codebefore)s'
  1107.         '    iface = g_type_interface_peek('
  1108.         'g_type_class_peek(pyg_type_from_object(cls)), %(typecode)s);\n'
  1109.         '    if (iface->%(virtual)s)\n'
  1110.         '        %(setreturn)siface->%(virtual)s(%(arglist)s);\n'
  1111.         '    else {\n'
  1112.         '        PyErr_SetString(PyExc_NotImplementedError, '
  1113.         '"interface method %(name)s not implemented");\n'
  1114.         '        return NULL;\n'
  1115.         '    }\n'
  1116.         '%(codeafter)s\n'
  1117.         '}\n\n'
  1118.         )
  1119.  
  1120.     def get_initial_class_substdict(self):
  1121.         return { 'tp_basicsize'      : 'PyObject',
  1122.                  'tp_weaklistoffset' : '0',
  1123.                  'tp_dictoffset'     : '0'}
  1124.  
  1125.     def write_constructor(self):
  1126.         # interfaces have no constructors ...
  1127.         return '0'
  1128.     def write_getsets(self):
  1129.         # interfaces have no fields ...
  1130.         return '0'
  1131.  
  1132.     def _get_class_virtual_substdict(self, meth, cname, parent):
  1133.         substdict = self.get_initial_method_substdict(meth)
  1134.         substdict['virtual'] = substdict['name'].split('.')[1]
  1135.         substdict['cname'] = cname
  1136.         substdict['typecode'] = self.objinfo.typecode
  1137.         substdict['vtable'] = self.objinfo.vtable
  1138.         return substdict
  1139.  
  1140.     def write_virtuals(self):
  1141.         ## Now write reverse method wrappers, which let python code
  1142.         ## implement interface methods.
  1143.         # First, get methods from the defs files
  1144.         klass = self.objinfo.c_name
  1145.         proxies = []
  1146.         for meth in self.parser.find_virtuals(self.objinfo):
  1147.             method_name = self.objinfo.c_name + "__proxy_do_" + meth.name
  1148.             if self.overrides.is_ignored(method_name):
  1149.                 continue
  1150.             try:
  1151.                 if self.overrides.is_overriden(method_name):
  1152.                     if not self.overrides.is_already_included(method_name):
  1153.                         data = self.overrides.override(method_name)
  1154.                         self.write_function(method_name, data)
  1155.                 else:
  1156.                     # write proxy ...
  1157.                     ret, props = argtypes.matcher.get_reverse_ret(meth.ret)
  1158.                     wrapper = reversewrapper.ReverseWrapper(
  1159.                         '_wrap_' + method_name, is_static=True)
  1160.                     wrapper.set_return_type(ret(wrapper, **props))
  1161.                     wrapper.add_parameter(reversewrapper.PyGObjectMethodParam(
  1162.                         wrapper, "self", method_name="do_" + meth.name,
  1163.                         c_type=(klass + ' *')))
  1164.                     for param in meth.params:
  1165.                         handler, props = argtypes.matcher.get_reverse(
  1166.                             param.ptype)
  1167.                         props["direction"] = param.pdir
  1168.                         wrapper.add_parameter(
  1169.                             handler(wrapper, param.pname, **props))
  1170.                     buf = reversewrapper.MemoryCodeSink()
  1171.                     wrapper.generate(buf)
  1172.                     self.fp.write(buf.flush())
  1173.                 proxies.append((fixname(meth.name), '_wrap_' + method_name))
  1174.                 iproxies_coverage.declare_wrapped()
  1175.             except argtypes.ArgTypeError, ex:
  1176.                 iproxies_coverage.declare_not_wrapped()
  1177.                 proxies.append((fixname(meth.name), None))
  1178.                 sys.stderr.write('Could not write interface proxy %s.%s: %s\n'
  1179.                                 % (klass, meth.name, str(ex)))
  1180.  
  1181.         if not proxies or not [cname for name, cname in proxies if cname]:
  1182.             return
  1183.  
  1184.         ## Write an interface init function for this object
  1185.         funcname = "__%s__interface_init" % klass
  1186.         vtable = self.objinfo.vtable
  1187.         self.fp.write(
  1188.             '\nstatic void\n'
  1189.             '%(funcname)s(%(vtable)s *iface, PyTypeObject *pytype)\n'
  1190.             '{\n'
  1191.             '    %(vtable)s *parent_iface = '
  1192.             'g_type_interface_peek_parent(iface);\n'
  1193.             '    PyObject *py_method;\n'
  1194.             '\n'
  1195.             % vars())
  1196.  
  1197.         for name, cname in proxies:
  1198.             do_name = 'do_' + name
  1199.             if cname is None:
  1200.                 continue
  1201.  
  1202.             self.fp.write((
  1203.                 '    py_method = pytype? PyObject_GetAttrString('
  1204.                 '(PyObject *) pytype, "%(do_name)s") : NULL;\n'
  1205.                 '    if (py_method && !PyObject_TypeCheck(py_method, '
  1206.                 '&PyCFunction_Type)) {\n'
  1207.                 '        iface->%(name)s = %(cname)s;\n'
  1208.                 '    } else {\n'
  1209.                 '        PyErr_Clear();\n'
  1210.                 '        if (parent_iface) {\n'
  1211.                 '            iface->%(name)s = parent_iface->%(name)s;\n'
  1212.                 '        }\n'
  1213.                 '    Py_XDECREF(py_method);\n'
  1214.                 '    }\n'
  1215.                 ) % vars())
  1216.         self.fp.write('}\n\n')
  1217.         interface_info = "__%s__iinfo" % klass
  1218.         self.fp.write('''
  1219. static const GInterfaceInfo %s = {
  1220.     (GInterfaceInitFunc) %s,
  1221.     NULL,
  1222.     NULL
  1223. };
  1224. ''' % (interface_info, funcname))
  1225.         self.objinfo.interface_info = interface_info
  1226.  
  1227. class GBoxedWrapper(Wrapper):
  1228.     constructor_tmpl = (
  1229.         'static int\n'
  1230.         '_wrap_%(cname)s(PyGBoxed *self%(extraparams)s)\n'
  1231.         '{\n'
  1232.         '%(varlist)s'
  1233.         '%(parseargs)s'
  1234.         '%(codebefore)s'
  1235.         '    self->gtype = %(typecode)s;\n'
  1236.         '    self->free_on_dealloc = FALSE;\n'
  1237.         '    self->boxed = %(cname)s(%(arglist)s);\n'
  1238.         '%(codeafter)s\n'
  1239.         '    if (!self->boxed) {\n'
  1240.         '        PyErr_SetString(PyExc_RuntimeError, '
  1241.         '"could not create %(typename)s object");\n'
  1242.         '        return -1;\n'
  1243.         '    }\n'
  1244.         '    self->free_on_dealloc = TRUE;\n'
  1245.         '    return 0;\n'
  1246.         '}\n\n'
  1247.         )
  1248.  
  1249.     method_tmpl = (
  1250.         'static PyObject *\n'
  1251.         '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n'
  1252.         '{\n'
  1253.         '%(varlist)s'
  1254.         '%(parseargs)s'
  1255.         '%(codebefore)s'
  1256.         '    %(begin_allow_threads)s\n'
  1257.         '    %(setreturn)s%(cname)s(pyg_boxed_get(self, '
  1258.         '%(typename)s)%(arglist)s);\n'
  1259.         '    %(end_allow_threads)s\n'
  1260.         '%(codeafter)s\n'
  1261.         '}\n\n'
  1262.         )
  1263.  
  1264.     def get_initial_class_substdict(self):
  1265.         return { 'tp_basicsize'      : 'PyGBoxed',
  1266.                  'tp_weaklistoffset' : '0',
  1267.                  'tp_dictoffset'     : '0' }
  1268.  
  1269.     def get_field_accessor(self, fieldname):
  1270.         return 'pyg_boxed_get(self, %s)->%s' % (self.objinfo.c_name, fieldname)
  1271.  
  1272.     def get_initial_constructor_substdict(self, constructor):
  1273.         substdict = Wrapper.get_initial_constructor_substdict(
  1274.             self, constructor)
  1275.         substdict['typecode'] = self.objinfo.typecode
  1276.         return substdict
  1277.  
  1278. class GPointerWrapper(GBoxedWrapper):
  1279.     constructor_tmpl = (
  1280.         'static int\n'
  1281.         '_wrap_%(cname)s(PyGPointer *self%(extraparams)s)\n'
  1282.         '{\n'
  1283.         '%(varlist)s'
  1284.         '%(parseargs)s'
  1285.         '%(codebefore)s'
  1286.         '    self->gtype = %(typecode)s;\n'
  1287.         '    self->pointer = %(cname)s(%(arglist)s);\n'
  1288.         '%(codeafter)s\n'
  1289.         '    if (!self->pointer) {\n'
  1290.         '        PyErr_SetString(PyExc_RuntimeError, '
  1291.         '"could not create %(typename)s object");\n'
  1292.         '        return -1;\n'
  1293.         '    }\n'
  1294.         '    return 0;\n'
  1295.         '}\n\n'
  1296.         )
  1297.  
  1298.     method_tmpl = (
  1299.         'static PyObject *\n'
  1300.         '_wrap_%(cname)s(PyObject *self%(extraparams)s)\n'
  1301.         '{\n'
  1302.         '%(varlist)s'
  1303.         '%(parseargs)s'
  1304.         '%(codebefore)s'
  1305.         '    %(setreturn)s%(cname)s(pyg_pointer_get(self, '
  1306.         '%(typename)s)%(arglist)s);\n'
  1307.         '%(codeafter)s\n'
  1308.         '}\n\n'
  1309.         )
  1310.  
  1311.     def get_initial_class_substdict(self):
  1312.         return { 'tp_basicsize'      : 'PyGPointer',
  1313.                  'tp_weaklistoffset' : '0',
  1314.                  'tp_dictoffset'     : '0' }
  1315.  
  1316.     def get_field_accessor(self, fieldname):
  1317.         return 'pyg_pointer_get(self, %s)->%s' % (self.objinfo.c_name,
  1318.                                                   fieldname)
  1319.  
  1320.     def get_initial_constructor_substdict(self, constructor):
  1321.         substdict = Wrapper.get_initial_constructor_substdict(
  1322.             self, constructor)
  1323.         substdict['typecode'] = self.objinfo.typecode
  1324.         return substdict
  1325.  
  1326. class SourceWriter:
  1327.     def __init__(self, parser, overrides, prefix, fp=FileOutput(sys.stdout)):
  1328.         self.parser = parser
  1329.         self.overrides = overrides
  1330.         self.prefix = prefix
  1331.         self.fp = fp
  1332.  
  1333.     def write(self, py_ssize_t_clean=False):
  1334.         argtypes.py_ssize_t_clean = py_ssize_t_clean
  1335.  
  1336.         self.write_headers(py_ssize_t_clean)
  1337.         self.write_imports()
  1338.         self.write_type_declarations()
  1339.         self.write_body()
  1340.         self.write_classes()
  1341.  
  1342.         wrapper = Wrapper(self.parser, None, self.overrides, self.fp)
  1343.         wrapper.write_functions(self, self.prefix)
  1344.  
  1345.         if not self.overrides.dynamicnamespace:
  1346.             self.write_enums()
  1347.         self.write_extension_init()
  1348.         self.write_registers()
  1349.         
  1350.         argtypes.py_ssize_t_clean = False
  1351.  
  1352.     def write_headers(self, py_ssize_t_clean):
  1353.         self.fp.write('/* -- THIS FILE IS GENERATED - DO NOT EDIT */')
  1354.         self.fp.write('/* -*- Mode: C; c-basic-offset: 4 -*- */\n\n')
  1355.         if py_ssize_t_clean:
  1356.             self.fp.write('#define PY_SSIZE_T_CLEAN\n')
  1357.         self.fp.write('#include <Python.h>\n\n\n')
  1358.         if py_ssize_t_clean:
  1359.             self.fp.write('''
  1360.  
  1361. #if PY_VERSION_HEX < 0x02050000
  1362. typedef int Py_ssize_t;
  1363. #define PY_SSIZE_T_MAX INT_MAX
  1364. #define PY_SSIZE_T_MIN INT_MIN
  1365. typedef inquiry lenfunc;
  1366. typedef intargfunc ssizeargfunc;
  1367. typedef intobjargproc ssizeobjargproc;
  1368. #endif
  1369.  
  1370. ''')
  1371.         self.fp.write(self.overrides.get_headers())
  1372.         self.fp.resetline()
  1373.         self.fp.write('\n\n')
  1374.  
  1375.     def write_imports(self):
  1376.         self.fp.write('/* ---------- types from other modules ---------- */\n')
  1377.         for module, pyname, cname in self.overrides.get_imports():
  1378.             self.fp.write('static PyTypeObject *_%s;\n' % cname)
  1379.             self.fp.write('#define %s (*_%s)\n' % (cname, cname))
  1380.         self.fp.write('\n\n')
  1381.  
  1382.     def write_type_declarations(self):
  1383.         #todo use 'static' if used only in one file
  1384.         self.fp.write('/* ---------- forward type declarations ---------- */\n')
  1385.         for obj in self.parser.boxes:
  1386.             if not self.overrides.is_type_ignored(obj.c_name):
  1387.                 self.fp.write('PyTypeObject G_GNUC_INTERNAL Py' + obj.c_name + '_Type;\n')
  1388.         for obj in self.parser.objects:
  1389.             if not self.overrides.is_type_ignored(obj.c_name):
  1390.                 self.fp.write('PyTypeObject G_GNUC_INTERNAL Py' + obj.c_name + '_Type;\n')
  1391.         for interface in self.parser.interfaces:
  1392.             if not self.overrides.is_type_ignored(interface.c_name):
  1393.                 self.fp.write('PyTypeObject G_GNUC_INTERNAL Py' + interface.c_name + '_Type;\n')
  1394.         self.fp.write('\n')
  1395.  
  1396.     def write_body(self):
  1397.         self.fp.write(self.overrides.get_body())
  1398.         self.fp.resetline()
  1399.         self.fp.write('\n\n')
  1400.  
  1401.     def _sort_parent_children(self, objects):
  1402.         objects = list(objects)
  1403.         modified = True
  1404.         while modified:
  1405.             modified = False
  1406.             parent_index = None
  1407.             child_index = None
  1408.             for i, obj in enumerate(objects):
  1409.                 if obj.parent == 'GObject':
  1410.                     continue
  1411.                 if obj.parent not in [info.c_name for info in objects[:i]]:
  1412.                     for j, info in enumerate(objects[i+1:]):
  1413.                         if info.c_name == obj.parent:
  1414.                             parent_index = i + 1 + j
  1415.                             child_index = i
  1416.                             break
  1417.                     else:
  1418.                         continue
  1419.                     break
  1420.             if child_index is not None and parent_index is not None:
  1421.                 if child_index != parent_index:
  1422.                     objects.insert(child_index, objects.pop(parent_index))
  1423.                     modified = True
  1424.         return objects
  1425.  
  1426.     def write_classes(self):
  1427.         ## Sort the objects, so that we generate code for the parent types
  1428.         ## before their children.
  1429.         objects = self._sort_parent_children(self.parser.objects)
  1430.  
  1431.         for klass, items in ((GBoxedWrapper, self.parser.boxes),
  1432.                              (GPointerWrapper, self.parser.pointers),
  1433.                              (GObjectWrapper, objects),
  1434.                              (GInterfaceWrapper, self.parser.interfaces)):
  1435.             for item in items:
  1436.                 instance = klass(self.parser, item, self.overrides, self.fp)
  1437.                 instance.write_class()
  1438.                 self.fp.write('\n')
  1439.  
  1440.     def get_enums(self):
  1441.         enums = []
  1442.         for enum in self.parser.enums:
  1443.             if self.overrides.is_type_ignored(enum.c_name):
  1444.                 continue
  1445.             enums.append(enum)
  1446.         return enums
  1447.  
  1448.     def write_enums(self):
  1449.         if not self.parser.enums:
  1450.             return
  1451.  
  1452.         self.fp.write('\n/* ----------- enums and flags ----------- */\n\n')
  1453.         self.fp.write(
  1454.             'void\n' + self.prefix +
  1455.             '_add_constants(PyObject *module, const gchar *strip_prefix)\n{\n')
  1456.  
  1457.         self.fp.write(
  1458.             '#ifdef VERSION\n'
  1459.             '    PyModule_AddStringConstant(module, "__version__", VERSION);\n'
  1460.             '#endif\n')
  1461.  
  1462.         for enum in self.get_enums():
  1463.             if enum.typecode is None:
  1464.                 for nick, value in enum.values:
  1465.                     self.fp.write(
  1466.                         '    PyModule_AddIntConstant(module, '
  1467.                         '(char *) pyg_constant_strip_prefix("%s", strip_prefix), %s);\n'
  1468.                         % (value, value))
  1469.             else:
  1470.                 if enum.deftype == 'enum':
  1471.                     self.fp.write('  pyg_enum_add(module, "%s", strip_prefix, %s);\n'
  1472.                                   % (enum.name, enum.typecode))
  1473.                 else:
  1474.                     self.fp.write('  pyg_flags_add(module, "%s", strip_prefix, %s);\n'
  1475.                                   % (enum.name, enum.typecode))
  1476.  
  1477.         self.fp.write('\n')
  1478.         self.fp.write('  if (PyErr_Occurred())\n')
  1479.         self.fp.write('    PyErr_Print();\n')
  1480.         self.fp.write('}\n\n')
  1481.  
  1482.     def write_object_imports(self, retval=''):
  1483.         imports = self.overrides.get_imports()[:]
  1484.         if not imports:
  1485.             return
  1486.  
  1487.         bymod = {}
  1488.         for module, pyname, cname in imports:
  1489.             bymod.setdefault(module, []).append((pyname, cname))
  1490.         self.fp.write('    PyObject *module;\n\n')
  1491.         for module in bymod:
  1492.             self.fp.write(
  1493.                 '    if ((module = PyImport_ImportModule("%s")) != NULL) {\n'
  1494.                 % module)
  1495.             #self.fp.write(
  1496.             #    '        PyObject *moddict = PyModule_GetDict(module);\n\n')
  1497.             for pyname, cname in bymod[module]:
  1498.                 #self.fp.write(
  1499.                 #    '        _%s = (PyTypeObject *)PyDict_GetItemString('
  1500.                 #    'moddict, "%s");\n' % (cname, pyname))
  1501.                 self.fp.write(
  1502.                     '        _%s = (PyTypeObject *)PyObject_GetAttrString('
  1503.                     'module, "%s");\n' % (cname, pyname))
  1504.                 self.fp.write('        if (_%s == NULL) {\n' % cname)
  1505.                 self.fp.write('            PyErr_SetString(PyExc_ImportError,\n')
  1506.                 self.fp.write('                "cannot import name %s from %s");\n'
  1507.                          % (pyname, module))
  1508.                 self.fp.write('            return %s;\n' % retval)
  1509.                 self.fp.write('        }\n')
  1510.             self.fp.write('    } else {\n')
  1511.             self.fp.write('        PyErr_SetString(PyExc_ImportError,\n')
  1512.             self.fp.write('            "could not import %s");\n' % module)
  1513.             self.fp.write('        return %s;\n' % retval)
  1514.             self.fp.write('    }\n')
  1515.         self.fp.write('\n')
  1516.  
  1517.     def write_extension_init(self):
  1518.         self.fp.write('/* initialise stuff extension classes */\n')
  1519.         self.fp.write('void\n' + self.prefix + '_register_classes(PyObject *d)\n{\n')
  1520.         self.write_object_imports()
  1521.         self.fp.write(self.overrides.get_init() + '\n')
  1522.         self.fp.resetline()
  1523.  
  1524.     def get_classes(self):
  1525.         objects = self.parser.objects[:]
  1526.         pos = 0
  1527.         while pos < len(objects):
  1528.             parent = objects[pos].parent
  1529.             for i in range(pos+1, len(objects)):
  1530.                 if objects[i].c_name == parent:
  1531.                     objects.insert(i+1, objects[pos])
  1532.                     del objects[pos]
  1533.                     break
  1534.             else:
  1535.                 pos = pos + 1
  1536.  
  1537.         retval = []
  1538.         for obj in objects:
  1539.             if self.overrides.is_type_ignored(obj.c_name):
  1540.                 continue
  1541.             bases = []
  1542.             if obj.parent != None:
  1543.                 bases.append(obj.parent)
  1544.             bases = bases + obj.implements
  1545.             retval.append((obj, bases))
  1546.  
  1547.         return retval
  1548.  
  1549.     def write_registers(self):
  1550.         for boxed in self.parser.boxes:
  1551.             if not self.overrides.is_type_ignored(boxed.c_name):
  1552.                 self.fp.write('    pyg_register_boxed(d, "' + boxed.name +
  1553.                               '", ' + boxed.typecode +
  1554.                               ', &Py' + boxed.c_name +
  1555.                           '_Type);\n')
  1556.         for pointer in self.parser.pointers:
  1557.             if not self.overrides.is_type_ignored(pointer.c_name):
  1558.                 self.fp.write('    pyg_register_pointer(d, "' + pointer.name +
  1559.                               '", ' + pointer.typecode +
  1560.                               ', &Py' + pointer.c_name + '_Type);\n')
  1561.         for interface in self.parser.interfaces:
  1562.             if not self.overrides.is_type_ignored(interface.c_name):
  1563.                 self.fp.write('    pyg_register_interface(d, "'
  1564.                               + interface.name + '", '+ interface.typecode
  1565.                               + ', &Py' + interface.c_name + '_Type);\n')
  1566.                 if interface.interface_info is not None:
  1567.                     self.fp.write('    pyg_register_interface_info(%s, &%s);\n' %
  1568.                                   (interface.typecode, interface.interface_info))
  1569.  
  1570.         if not self.overrides.dynamicnamespace:
  1571.             for obj, bases in self.get_classes():
  1572.                 self.write_class(obj, bases)
  1573.         else:
  1574.             for obj, bases in self.get_classes():
  1575.                 self.fp.write(
  1576.                     '    pyg_type_register_custom_callback("%s", '
  1577.                     '(PyGTypeRegistrationFunction)%s_register_type, d);\n' %
  1578.                     (obj.c_name, obj.c_name))
  1579.  
  1580.         self.fp.write('}\n')
  1581.  
  1582.     def _can_direct_ref(self, base):
  1583.         if not self.overrides.dynamicnamespace:
  1584.             return True
  1585.         if base == 'GObject':
  1586.             return True
  1587.         obj = get_object_by_name(base)
  1588.         if obj.module.lower() != self.overrides.modulename:
  1589.             return True
  1590.         return False
  1591.  
  1592.     def write_class(self, obj, bases, indent=1):
  1593.         indent_str = ' ' * (indent * 4)
  1594.         if bases:
  1595.             bases_str = 'Py_BuildValue("(%s)"' % (len(bases) * 'O')
  1596.  
  1597.             for base in bases:
  1598.                 if self._can_direct_ref(base):
  1599.                     bases_str += ', &Py%s_Type' % base
  1600.                 else:
  1601.                     baseobj = get_object_by_name(base)
  1602.                     bases_str += ', PyObject_GetAttrString(m, "%s")' % baseobj.name
  1603.             bases_str += ')'
  1604.         else:
  1605.             bases_str = 'NULL'
  1606.  
  1607.         self.fp.write(
  1608.                 '%(indent)spygobject_register_class(d, "%(c_name)s", %(typecode)s, &Py%(c_name)s_Type, %(bases)s);\n'
  1609.                 % dict(indent=indent_str, c_name=obj.c_name, typecode=obj.typecode, bases=bases_str))
  1610.  
  1611.         if obj.has_new_constructor_api:
  1612.             self.fp.write(
  1613.                 indent_str + 'pyg_set_object_has_new_constructor(%s);\n' %
  1614.                 obj.typecode)
  1615.         else:
  1616.             print >> sys.stderr, (
  1617.                 "Warning: Constructor for %s needs to be updated to new API\n"
  1618.                 "         See http://live.gnome.org/PyGTK_2fWhatsNew28"
  1619.                 "#update-constructors") % obj.c_name
  1620.  
  1621.         if obj.class_init_func is not None:
  1622.             self.fp.write(
  1623.                 indent_str + 'pyg_register_class_init(%s, %s);\n' %
  1624.                 (obj.typecode, obj.class_init_func))
  1625.  
  1626. _objects = {}
  1627.  
  1628. def get_object_by_name(c_name):
  1629.     global _objects
  1630.     return _objects[c_name]
  1631.  
  1632. def register_types(parser):
  1633.     global _objects
  1634.     for boxed in parser.boxes:
  1635.         argtypes.matcher.register_boxed(boxed.c_name, boxed.typecode)
  1636.         _objects[boxed.c_name] = boxed
  1637.     for pointer in parser.pointers:
  1638.         argtypes.matcher.register_pointer(pointer.c_name, pointer.typecode)
  1639.     for obj in parser.objects:
  1640.         argtypes.matcher.register_object(obj.c_name, obj.parent, obj.typecode)
  1641.         _objects[obj.c_name] = obj
  1642.     for iface in parser.interfaces:
  1643.         argtypes.matcher.register_object(iface.c_name, None, iface.typecode)
  1644.         _objects[iface.c_name] = iface
  1645.     for enum in parser.enums:
  1646.         if enum.deftype == 'flags':
  1647.             argtypes.matcher.register_flag(enum.c_name, enum.typecode)
  1648.         else:
  1649.             argtypes.matcher.register_enum(enum.c_name, enum.typecode)
  1650.  
  1651. usage = 'usage: codegen.py [-o overridesfile] [-p prefix] defsfile'
  1652. def main(argv):
  1653.     o = override.Overrides()
  1654.     prefix = 'pygtk'
  1655.     outfilename = None
  1656.     errorfilename = None
  1657.     opts, args = getopt.getopt(argv[1:], "o:p:r:t:D:I:",
  1658.                         ["override=", "prefix=", "register=", "outfilename=",
  1659.                          "load-types=", "errorfilename=", "py_ssize_t-clean"])
  1660.     defines = {} # -Dkey[=val] options
  1661.     py_ssize_t_clean = False
  1662.     for opt, arg in opts:
  1663.         if opt in ('-o', '--override'):
  1664.             o = override.Overrides(arg)
  1665.         elif opt in ('-p', '--prefix'):
  1666.             prefix = arg
  1667.         elif opt in ('-r', '--register'):
  1668.             # Warning: user has to make sure all -D options appear before -r
  1669.             p = defsparser.DefsParser(arg, defines)
  1670.             p.startParsing()
  1671.             register_types(p)
  1672.             del p
  1673.         elif opt == '--outfilename':
  1674.             outfilename = arg
  1675.         elif opt == '--errorfilename':
  1676.             errorfilename = arg
  1677.         elif opt in ('-t', '--load-types'):
  1678.             globals = {}
  1679.             execfile(arg, globals)
  1680.         elif opt == '-D':
  1681.             nameval = arg.split('=')
  1682.             try:
  1683.                 defines[nameval[0]] = nameval[1]
  1684.             except IndexError:
  1685.                 defines[nameval[0]] = None
  1686.         elif opt == '-I':
  1687.             defsparser.include_path.insert(0, arg)
  1688.         elif opt == '--py_ssize_t-clean':
  1689.             py_ssize_t_clean = True
  1690.     if len(args) < 1:
  1691.         print >> sys.stderr, usage
  1692.         return 1
  1693.     if errorfilename:
  1694.         sys.stderr = open(errorfilename, "w")
  1695.     p = defsparser.DefsParser(args[0], defines)
  1696.     if not outfilename:
  1697.         outfilename = os.path.splitext(args[0])[0] + '.c'
  1698.  
  1699.     p.startParsing()
  1700.  
  1701.     register_types(p)
  1702.     sw = SourceWriter(p, o, prefix, FileOutput(sys.stdout, outfilename))
  1703.     sw.write(py_ssize_t_clean)
  1704.  
  1705.     functions_coverage.printstats()
  1706.     methods_coverage.printstats()
  1707.     vproxies_coverage.printstats()
  1708.     vaccessors_coverage.printstats()
  1709.     iproxies_coverage.printstats()
  1710.  
  1711. if __name__ == '__main__':
  1712.     sys.exit(main(sys.argv))
  1713.