2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008 Johan Dahlin
4 # Copyright (C) 2008, 2009 Red Hat, Inc.
6 # This library is free software; you can redistribute it and/or
7 # modify it under the terms of the GNU Lesser General Public
8 # License as published by the Free Software Foundation; either
9 # version 2 of the License, or (at your option) any later version.
11 # This library is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 # Lesser General Public License for more details.
16 # You should have received a copy of the GNU Lesser General Public
17 # License along with this library; if not, write to the
18 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 # Boston, MA 02111-1307, USA.
22 from __future__ import with_statement
25 from ctypes.util import find_library
27 from .ast import (Alias, Array, Bitfield, Callback, Class, Constant, Enum,
28 Function, Interface, List, Map, Member, Struct, Union,
30 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
31 GLibFlags, GLibObject, GLibInterface,
33 from .xmlwriter import XMLWriter
36 class GIRWriter(XMLWriter):
38 def __init__(self, namespace, shlibs, includes, pkgs, c_includes):
39 super(GIRWriter, self).__init__()
41 '''This file was automatically generated from C sources - DO NOT EDIT!
42 To affect the contents of this file, edit the original C definitions,
43 and/or use gtk-doc annotations. ''')
44 self._write_repository(namespace, shlibs, includes, pkgs, c_includes)
46 def _write_repository(self, namespace, shlibs, includes=None,
47 packages=None, c_includes=None):
49 includes = frozenset()
51 packages = frozenset()
52 if c_includes is None:
53 c_includes = frozenset()
56 ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
57 ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
58 ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
60 with self.tagcontext('repository', attrs):
61 for include in sorted(includes):
62 self._write_include(include)
63 for pkg in sorted(set(packages)):
64 self._write_pkgconfig_pkg(pkg)
65 for c_include in sorted(set(c_includes)):
66 self._write_c_include(c_include)
67 self._write_namespace(namespace, shlibs)
69 def _write_include(self, include):
70 attrs = [('name', include.name), ('version', include.version)]
71 self.write_tag('include', attrs)
73 def _write_pkgconfig_pkg(self, package):
74 attrs = [('name', package)]
75 self.write_tag('package', attrs)
77 def _write_c_include(self, c_include):
78 attrs = [('name', c_include)]
79 self.write_tag('c:include', attrs)
81 def _write_namespace(self, namespace, shlibs):
84 found_libname = find_library(l)
87 libraries.append(os.path.basename(found_libname))
89 attrs = [('name', namespace.name),
90 ('version', namespace.version),
91 ('shared-library', ','.join(libraries))]
92 with self.tagcontext('namespace', attrs):
93 # We define a custom sorting function here because
94 # we want aliases to be first. They're a bit
95 # special because the typelib compiler expands them.
97 if isinstance(a, Alias):
98 if isinstance(b, Alias):
99 return cmp(a.name, b.name)
102 elif isinstance(b, Alias):
106 for node in sorted(namespace.nodes, cmp=nscmp):
107 self._write_node(node)
109 def _write_node(self, node):
110 if isinstance(node, Function):
111 self._write_function(node)
112 elif isinstance(node, Enum):
113 self._write_enum(node)
114 elif isinstance(node, Bitfield):
115 self._write_bitfield(node)
116 elif isinstance(node, (Class, Interface)):
117 self._write_class(node)
118 elif isinstance(node, Callback):
119 self._write_callback(node)
120 elif isinstance(node, Struct):
121 self._write_record(node)
122 elif isinstance(node, Union):
123 self._write_union(node)
124 elif isinstance(node, GLibBoxed):
125 self._write_boxed(node)
126 elif isinstance(node, Member):
127 # FIXME: atk_misc_instance singleton
129 elif isinstance(node, Alias):
130 self._write_alias(node)
131 elif isinstance(node, Constant):
132 self._write_constant(node)
134 print 'WRITER: Unhandled node', node
136 def _append_version(self, node, attrs):
138 attrs.append(('version', node.version))
140 def _write_attributes(self, node):
141 for key, value in node.attributes:
142 self.write_tag('attribute', [('name', key), ('value', value)])
144 def _append_deprecated(self, node, attrs):
146 attrs.append(('deprecated', node.deprecated))
147 if node.deprecated_version:
148 attrs.append(('deprecated-version',
149 node.deprecated_version))
151 def _append_throws(self, func, attrs):
153 attrs.append(('throws', '1'))
155 def _write_alias(self, alias):
156 attrs = [('name', alias.name), ('target', alias.target)]
157 if alias.ctype is not None:
158 attrs.append(('c:type', alias.ctype))
159 self.write_tag('alias', attrs)
161 def _write_function(self, func, tag_name='function'):
162 attrs = [('name', func.name),
163 ('c:identifier', func.symbol)]
165 attrs.append(('doc', func.doc))
166 self._append_version(func, attrs)
167 self._append_deprecated(func, attrs)
168 self._append_throws(func, attrs)
169 with self.tagcontext(tag_name, attrs):
170 self._write_attributes(func)
171 self._write_return_type(func.retval)
172 self._write_parameters(func.parameters)
174 def _write_method(self, method):
175 self._write_function(method, tag_name='method')
177 def _write_static_method(self, method):
178 self._write_function(method, tag_name='function')
180 def _write_constructor(self, method):
181 self._write_function(method, tag_name='constructor')
183 def _write_return_type(self, return_):
187 assert return_.transfer is not None, return_
190 attrs.append(('transfer-ownership', return_.transfer))
192 attrs.append(('doc', return_.doc))
193 with self.tagcontext('return-value', attrs):
194 self._write_type(return_.type)
196 def _write_parameters(self, parameters):
199 with self.tagcontext('parameters'):
200 for parameter in parameters:
201 self._write_parameter(parameter)
203 def _write_parameter(self, parameter):
204 assert parameter.transfer is not None, parameter
207 if parameter.name is not None:
208 attrs.append(('name', parameter.name))
209 if parameter.direction != 'in':
210 attrs.append(('direction', parameter.direction))
211 attrs.append(('transfer-ownership',
213 if parameter.allow_none:
214 attrs.append(('allow-none', '1'))
216 attrs.append(('scope', parameter.scope))
217 if parameter.closure_index >= 0:
218 attrs.append(('closure', '%d' % parameter.closure_index))
219 if parameter.destroy_index >= 0:
220 attrs.append(('destroy', '%d' % parameter.destroy_index))
222 attrs.append(('doc', parameter.doc))
223 with self.tagcontext('parameter', attrs):
224 self._write_type(parameter.type)
226 def _type_to_string(self, ntype):
227 if isinstance(ntype, basestring):
231 def _write_type(self, ntype, relation=None):
232 if isinstance(ntype, basestring):
236 typename = ntype.name
237 type_cname = ntype.ctype
238 if isinstance(ntype, Varargs):
239 with self.tagcontext('varargs', []):
242 if isinstance(ntype, Array):
244 if not ntype.zeroterminated:
245 attrs.append(('zero-terminated', '0'))
246 if ntype.length_param_index >= 0:
247 attrs.append(('length', '%d' % (ntype.length_param_index, )))
248 attrs.append(('c:type', ntype.ctype))
249 if ntype.size is not None:
250 attrs.append(('fixed-size', ntype.size))
251 with self.tagcontext('array', attrs):
252 self._write_type(ntype.element_type)
254 attrs = [('name', self._type_to_string(ntype))]
255 # FIXME: figure out if type references a basic type
256 # or a boxed/class/interface etc. and skip
257 # writing the ctype if the latter.
258 if type_cname is not None:
259 attrs.append(('c:type', type_cname))
260 if isinstance(ntype, List) and ntype.element_type:
261 with self.tagcontext('type', attrs):
262 self._write_type(ntype.element_type)
264 if isinstance(ntype, Map) and ntype.key_type:
265 with self.tagcontext('type', attrs):
266 self._write_type(ntype.key_type)
267 self._write_type(ntype.value_type)
269 # Not a special type, just write it out
270 self.write_tag('type', attrs)
272 def _write_enum(self, enum):
273 attrs = [('name', enum.name)]
275 attrs.append(('doc', enum.doc))
276 self._append_version(enum, attrs)
277 self._append_deprecated(enum, attrs)
278 if isinstance(enum, GLibEnum):
279 attrs.extend([('glib:type-name', enum.type_name),
280 ('glib:get-type', enum.get_type),
281 ('c:type', enum.ctype)])
283 attrs.append(('glib:error-quark', enum.error_quark))
285 attrs.append(('c:type', enum.symbol))
287 with self.tagcontext('enumeration', attrs):
288 self._write_attributes(enum)
289 for member in enum.members:
290 self._write_member(member)
292 def _write_bitfield(self, bitfield):
293 attrs = [('name', bitfield.name)]
295 attrs.append(('doc', bitfield.doc))
296 self._append_version(bitfield, attrs)
297 self._append_deprecated(bitfield, attrs)
298 if isinstance(bitfield, GLibFlags):
299 attrs.extend([('glib:type-name', bitfield.type_name),
300 ('glib:get-type', bitfield.get_type),
301 ('c:type', bitfield.ctype)])
303 attrs.append(('c:type', bitfield.symbol))
304 with self.tagcontext('bitfield', attrs):
305 self._write_attributes(bitfield)
306 for member in bitfield.members:
307 self._write_member(member)
309 def _write_member(self, member):
310 attrs = [('name', member.name),
311 ('value', str(member.value)),
312 ('c:identifier', member.symbol)]
313 if isinstance(member, GLibEnumMember):
314 attrs.append(('glib:nick', member.nick))
315 self.write_tag('member', attrs)
317 def _write_constant(self, constant):
318 attrs = [('name', constant.name),
319 ('value', str(constant.value))]
320 with self.tagcontext('constant', attrs):
321 self._write_type(constant.type)
323 def _write_class(self, node):
324 attrs = [('name', node.name),
325 ('c:type', node.ctype)]
327 attrs.append(('doc', node.doc))
328 self._append_version(node, attrs)
329 self._append_deprecated(node, attrs)
330 if isinstance(node, Class):
332 if node.parent is not None:
333 attrs.append(('parent', node.parent))
335 attrs.append(('abstract', '1'))
337 tag_name = 'interface'
338 if isinstance(node, (GLibObject, GLibInterface)):
339 attrs.append(('glib:type-name', node.type_name))
341 attrs.append(('glib:get-type', node.get_type))
342 if node.glib_type_struct:
343 attrs.append(('glib:type-struct', node.glib_type_struct.name))
344 with self.tagcontext(tag_name, attrs):
345 self._write_attributes(node)
346 if isinstance(node, GLibObject):
347 for iface in node.interfaces:
348 self.write_tag('implements', [('name', iface)])
349 if isinstance(node, Interface):
350 for iface in node.prerequisites:
351 self.write_tag('prerequisite', [('name', iface)])
352 if isinstance(node, Class):
353 for method in node.constructors:
354 self._write_constructor(method)
355 for method in node.static_methods:
356 self._write_static_method(method)
357 for method in node.methods:
358 self._write_method(method)
359 for prop in node.properties:
360 self._write_property(prop)
361 for field in node.fields:
362 self._write_field(field)
363 for signal in node.signals:
364 self._write_signal(signal)
366 def _write_boxed(self, boxed):
367 attrs = [('c:type', boxed.ctype),
368 ('glib:name', boxed.name)]
370 attrs.append(('doc', boxed.doc))
371 attrs.extend(self._boxed_attrs(boxed))
372 with self.tagcontext('glib:boxed', attrs):
373 self._write_attributes(boxed)
374 for method in boxed.constructors:
375 self._write_constructor(method)
376 for method in boxed.methods:
377 self._write_method(method)
379 def _write_property(self, prop):
380 attrs = [('name', prop.name)]
381 self._append_version(prop, attrs)
382 self._append_deprecated(prop, attrs)
383 # Properties are assumed to be readable (see also generate.c)
384 if not prop.readable:
385 attrs.append(('readable', '0'))
387 attrs.append(('writable', '1'))
389 attrs.append(('construct', '1'))
390 if prop.construct_only:
391 attrs.append(('construct-only', '1'))
393 attrs.append(('doc', prop.doc))
394 with self.tagcontext('property', attrs):
395 self._write_attributes(prop)
396 self._write_type(prop.type)
398 def _write_callback(self, callback):
399 # FIXME: reuse _write_function
400 attrs = [('name', callback.name), ('c:type', callback.ctype)]
402 attrs.append(('doc', callback.doc))
403 self._append_version(callback, attrs)
404 self._append_deprecated(callback, attrs)
405 self._append_throws(callback, attrs)
406 with self.tagcontext('callback', attrs):
407 self._write_attributes(callback)
408 self._write_return_type(callback.retval)
409 self._write_parameters(callback.parameters)
411 def _boxed_attrs(self, boxed):
412 return [('glib:type-name', boxed.type_name),
413 ('glib:get-type', boxed.get_type)]
415 def _write_record(self, record, extra_attrs=[]):
416 attrs = list(extra_attrs)
417 if record.name is not None:
418 attrs.append(('name', record.name))
419 if record.symbol is not None: # the record might be anonymous
420 attrs.append(('c:type', record.symbol))
422 attrs.append(('disguised', '1'))
423 if isinstance(record, GLibRecord):
424 if record.is_gtype_struct_for:
425 attrs.append(('glib:is-gtype-struct-for',
426 record.is_gtype_struct_for))
428 attrs.append(('doc', record.doc))
429 self._append_version(record, attrs)
430 self._append_deprecated(record, attrs)
431 if isinstance(record, GLibBoxed):
432 attrs.extend(self._boxed_attrs(record))
433 with self.tagcontext('record', attrs):
434 self._write_attributes(record)
436 for field in record.fields:
437 self._write_field(field)
438 for method in record.constructors:
439 self._write_constructor(method)
440 for method in record.methods:
441 self._write_method(method)
443 def _write_union(self, union):
445 if union.name is not None:
446 attrs.append(('name', union.name))
447 if union.symbol is not None: # the union might be anonymous
448 attrs.append(('c:type', union.symbol))
450 attrs.append(('doc', union.doc))
451 self._append_version(union, attrs)
452 self._append_deprecated(union, attrs)
453 if isinstance(union, GLibBoxed):
454 attrs.extend(self._boxed_attrs(union))
455 with self.tagcontext('union', attrs):
456 self._write_attributes(union)
458 for field in union.fields:
459 self._write_field(field)
460 for method in union.constructors:
461 self._write_constructor(method)
462 for method in union.methods:
463 self._write_method(method)
465 def _write_field(self, field):
466 if isinstance(field, Function):
467 self._write_method(field)
470 if isinstance(field, Callback):
471 self._write_callback(field)
472 elif isinstance(field, Struct):
473 self._write_record(field)
474 elif isinstance(field, Union):
475 self._write_union(field)
477 attrs = [('name', field.name)]
478 # Fields are assumed to be read-only
479 # (see also girparser.c and generate.c)
480 if not field.readable:
481 attrs.append(('readable', '0'))
483 attrs.append(('writable', '1'))
485 attrs.append(('bits', str(field.bits)))
486 with self.tagcontext('field', attrs):
487 self._write_attributes(field)
488 self._write_type(field.type)
490 def _write_signal(self, signal):
491 attrs = [('name', signal.name)]
493 attrs.append(('doc', signal.doc))
494 self._append_version(signal, attrs)
495 self._append_deprecated(signal, attrs)
496 with self.tagcontext('glib:signal', attrs):
497 self._write_attributes(signal)
498 self._write_return_type(signal.retval)
499 self._write_parameters(signal.parameters)