2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008 Johan Dahlin
5 # This library is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU Lesser General Public
7 # License as published by the Free Software Foundation; either
8 # version 2 of the License, or (at your option) any later version.
10 # This library is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 # Lesser General Public License for more details.
15 # You should have received a copy of the GNU Lesser General Public
16 # License along with this library; if not, write to the
17 # Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 # Boston, MA 02111-1307, USA.
21 from __future__ import with_statement
24 from ctypes.util import find_library
26 from .ast import (Alias, Array, Bitfield, Callback, Class, Constant, Enum,
27 Function, Interface, List, Map, Member, Struct, Union,
29 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember,
30 GLibFlags, GLibObject, GLibInterface)
31 from .xmlwriter import XMLWriter
34 class GIRWriter(XMLWriter):
36 def __init__(self, namespace, shlibs, includes):
37 super(GIRWriter, self).__init__()
39 '''This file was automatically generated from C sources - DO NOT EDIT!
40 To affect the contents of this file, edit the original C definitions,
41 and/or use gtk-doc annotations. ''')
42 self._write_repository(namespace, shlibs, includes)
44 def _write_repository(self, namespace, shlibs, includes=set()):
47 ('xmlns', 'http://www.gtk.org/introspection/core/1.0'),
48 ('xmlns:c', 'http://www.gtk.org/introspection/c/1.0'),
49 ('xmlns:glib', 'http://www.gtk.org/introspection/glib/1.0'),
51 with self.tagcontext('repository', attrs):
52 for include in sorted(includes):
53 self._write_include(include)
54 self._write_namespace(namespace, shlibs)
56 def _write_include(self, include):
57 attrs = [('name', include.name), ('version', include.version)]
58 self.write_tag('include', attrs)
60 def _write_namespace(self, namespace, shlibs):
63 found_libname = find_library(l)
66 libraries.append(os.path.basename(found_libname))
68 attrs = [('name', namespace.name),
69 ('version', namespace.version),
70 ('shared-library', ','.join(libraries))]
71 with self.tagcontext('namespace', attrs):
72 for node in namespace.nodes:
73 self._write_node(node)
75 def _write_node(self, node):
76 if isinstance(node, Function):
77 self._write_function(node)
78 elif isinstance(node, Enum):
79 self._write_enum(node)
80 elif isinstance(node, Bitfield):
81 self._write_bitfield(node)
82 elif isinstance(node, (Class, Interface)):
83 self._write_class(node)
84 elif isinstance(node, Callback):
85 self._write_callback(node)
86 elif isinstance(node, Struct):
87 self._write_record(node)
88 elif isinstance(node, Union):
89 self._write_union(node)
90 elif isinstance(node, GLibBoxed):
91 self._write_boxed(node)
92 elif isinstance(node, Member):
93 # FIXME: atk_misc_instance singleton
95 elif isinstance(node, Alias):
96 self._write_alias(node)
97 elif isinstance(node, Constant):
98 self._write_constant(node)
100 print 'WRITER: Unhandled node', node
102 def _append_version(self, node, attrs):
104 attrs.append(('version', node.version))
106 def _append_deprecated(self, node, attrs):
108 attrs.append(('deprecated', node.deprecated))
109 if node.deprecated_version:
110 attrs.append(('deprecated-version',
111 node.deprecated_version))
113 def _append_throws(self, func, attrs):
115 attrs.append(('throws', '1'))
117 def _write_alias(self, alias):
118 attrs = [('name', alias.name), ('target', alias.target)]
119 if alias.ctype is not None:
120 attrs.append(('c:type', alias.ctype))
121 self.write_tag('alias', attrs)
123 def _write_function(self, func, tag_name='function'):
124 attrs = [('name', func.name),
125 ('c:identifier', func.symbol)]
127 attrs.append(('doc', func.doc))
128 self._append_version(func, attrs)
129 self._append_deprecated(func, attrs)
130 self._append_throws(func, attrs)
131 with self.tagcontext(tag_name, attrs):
132 self._write_return_type(func.retval)
133 self._write_parameters(func.parameters)
135 def _write_method(self, method):
136 self._write_function(method, tag_name='method')
138 def _write_static_method(self, method):
139 self._write_function(method, tag_name='function')
141 def _write_constructor(self, method):
142 self._write_function(method, tag_name='constructor')
144 def _write_return_type(self, return_):
148 assert return_.transfer is not None, return_
151 attrs.append(('transfer-ownership', return_.transfer))
153 attrs.append(('doc', return_.doc))
154 with self.tagcontext('return-value', attrs):
155 self._write_type(return_.type)
157 def _write_parameters(self, parameters):
160 with self.tagcontext('parameters'):
161 for parameter in parameters:
162 self._write_parameter(parameter)
164 def _write_parameter(self, parameter):
165 assert parameter.transfer is not None, parameter
168 if parameter.name is not None:
169 attrs.append(('name', parameter.name))
170 if parameter.direction != 'in':
171 attrs.append(('direction', parameter.direction))
172 attrs.append(('transfer-ownership',
174 if parameter.allow_none:
175 attrs.append(('allow-none', '1'))
177 attrs.append(('scope', parameter.scope))
178 if parameter.closure_index >= 0:
179 attrs.append(('closure', '%d' % parameter.closure_index))
180 if parameter.destroy_index >= 0:
181 attrs.append(('destroy', '%d' % parameter.destroy_index))
183 attrs.append(('doc', parameter.doc))
184 with self.tagcontext('parameter', attrs):
185 self._write_type(parameter.type)
187 def _type_to_string(self, ntype):
188 if isinstance(ntype, basestring):
192 def _write_type(self, ntype, relation=None):
193 if isinstance(ntype, basestring):
197 typename = ntype.name
198 type_cname = ntype.ctype
199 if isinstance(ntype, Varargs):
200 with self.tagcontext('varargs', []):
203 if isinstance(ntype, Array):
205 if not ntype.zeroterminated:
206 attrs.append(('zero-terminated', '0'))
207 if ntype.length_param_index >= 0:
208 attrs.append(('length', '%d' % (ntype.length_param_index, )))
209 attrs.append(('c:type', ntype.ctype))
210 if ntype.size is not None:
211 attrs.append(('fixed-size', ntype.size))
212 with self.tagcontext('array', attrs):
213 self._write_type(ntype.element_type)
215 attrs = [('name', self._type_to_string(ntype))]
216 # FIXME: figure out if type references a basic type
217 # or a boxed/class/interface etc. and skip
218 # writing the ctype if the latter.
219 if type_cname is not None:
220 attrs.append(('c:type', type_cname))
221 if isinstance(ntype, List) and ntype.element_type:
222 with self.tagcontext('type', attrs):
223 self._write_type(ntype.element_type)
225 if isinstance(ntype, Map) and ntype.key_type:
226 with self.tagcontext('type', attrs):
227 self._write_type(ntype.key_type)
228 self._write_type(ntype.value_type)
230 # Not a special type, just write it out
231 self.write_tag('type', attrs)
233 def _write_enum(self, enum):
234 attrs = [('name', enum.name)]
236 attrs.append(('doc', enum.doc))
237 self._append_version(enum, attrs)
238 self._append_deprecated(enum, attrs)
239 if isinstance(enum, GLibEnum):
240 attrs.extend([('glib:type-name', enum.type_name),
241 ('glib:get-type', enum.get_type),
242 ('c:type', enum.ctype)])
244 attrs.append(('glib:error-quark', enum.error_quark))
246 attrs.append(('c:type', enum.symbol))
248 with self.tagcontext('enumeration', attrs):
249 for member in enum.members:
250 self._write_member(member)
252 def _write_bitfield(self, bitfield):
253 attrs = [('name', bitfield.name)]
255 attrs.append(('doc', bitfield.doc))
256 self._append_version(bitfield, attrs)
257 self._append_deprecated(bitfield, attrs)
258 if isinstance(bitfield, GLibFlags):
259 attrs.extend([('glib:type-name', bitfield.type_name),
260 ('glib:get-type', bitfield.get_type),
261 ('c:type', bitfield.ctype)])
263 attrs.append(('c:type', bitfield.symbol))
264 with self.tagcontext('bitfield', attrs):
265 for member in bitfield.members:
266 self._write_member(member)
268 def _write_member(self, member):
269 attrs = [('name', member.name),
270 ('value', str(member.value)),
271 ('c:identifier', member.symbol)]
272 if isinstance(member, GLibEnumMember):
273 attrs.append(('glib:nick', member.nick))
274 self.write_tag('member', attrs)
276 def _write_constant(self, constant):
277 attrs = [('name', constant.name),
278 ('value', str(constant.value))]
279 with self.tagcontext('constant', attrs):
280 self._write_type(constant.type)
282 def _write_class(self, node):
283 attrs = [('name', node.name),
284 ('c:type', node.ctype)]
286 attrs.append(('doc', node.doc))
287 self._append_version(node, attrs)
288 self._append_deprecated(node, attrs)
289 if isinstance(node, Class):
291 if node.parent is not None:
292 attrs.append(('parent', node.parent))
294 attrs.append(('abstract', '1'))
296 tag_name = 'interface'
297 if isinstance(node, (GLibObject, GLibInterface)):
298 attrs.append(('glib:type-name', node.type_name))
300 attrs.append(('glib:get-type', node.get_type))
301 with self.tagcontext(tag_name, attrs):
302 if isinstance(node, GLibObject):
303 for iface in node.interfaces:
304 self.write_tag('implements', [('name', iface)])
305 if isinstance(node, Interface):
306 for iface in node.prerequisites:
307 self.write_tag('prerequisite', [('name', iface)])
308 if isinstance(node, Class):
309 for method in node.constructors:
310 self._write_constructor(method)
311 for method in node.static_methods:
312 self._write_static_method(method)
313 for method in node.methods:
314 self._write_method(method)
315 for prop in node.properties:
316 self._write_property(prop)
317 for field in node.fields:
318 self._write_field(field)
319 for signal in node.signals:
320 self._write_signal(signal)
322 def _write_boxed(self, boxed):
323 attrs = [('c:type', boxed.ctype),
324 ('glib:name', boxed.name)]
326 attrs.append(('doc', boxed.doc))
327 attrs.extend(self._boxed_attrs(boxed))
328 with self.tagcontext('glib:boxed', attrs):
329 for method in boxed.constructors:
330 self._write_constructor(method)
331 for method in boxed.methods:
332 self._write_method(method)
334 def _write_property(self, prop):
335 attrs = [('name', prop.name)]
336 self._append_version(prop, attrs)
337 self._append_deprecated(prop, attrs)
338 # Properties are assumed to be readable (see also generate.c)
339 if not prop.readable:
340 attrs.append(('readable', '0'))
342 attrs.append(('writable', '1'))
344 attrs.append(('construct', '1'))
345 if prop.construct_only:
346 attrs.append(('construct-only', '1'))
348 attrs.append(('doc', prop.doc))
349 with self.tagcontext('property', attrs):
350 self._write_type(prop.type)
352 def _write_callback(self, callback):
353 # FIXME: reuse _write_function
354 attrs = [('name', callback.name), ('c:type', callback.ctype)]
356 attrs.append(('doc', callback.doc))
357 self._append_version(callback, attrs)
358 self._append_deprecated(callback, attrs)
359 self._append_throws(callback, attrs)
360 with self.tagcontext('callback', attrs):
361 self._write_return_type(callback.retval)
362 self._write_parameters(callback.parameters)
364 def _boxed_attrs(self, boxed):
365 return [('glib:type-name', boxed.type_name),
366 ('glib:get-type', boxed.get_type)]
368 def _write_record(self, record):
369 attrs = [('name', record.name),
370 ('c:type', record.symbol)]
372 attrs.append(('disguised', '1'))
374 attrs.append(('doc', record.doc))
375 self._append_version(record, attrs)
376 self._append_deprecated(record, attrs)
377 if isinstance(record, GLibBoxed):
378 attrs.extend(self._boxed_attrs(record))
379 with self.tagcontext('record', attrs):
381 for field in record.fields:
382 self._write_field(field)
383 for method in record.constructors:
384 self._write_constructor(method)
385 for method in record.methods:
386 self._write_method(method)
388 def _write_union(self, union):
389 attrs = [('name', union.name),
390 ('c:type', union.symbol)]
392 attrs.append(('doc', union.doc))
393 self._append_version(union, attrs)
394 self._append_deprecated(union, attrs)
395 if isinstance(union, GLibBoxed):
396 attrs.extend(self._boxed_attrs(union))
397 with self.tagcontext('union', attrs):
399 for field in union.fields:
400 self._write_field(field)
401 for method in union.constructors:
402 self._write_constructor(method)
403 for method in union.methods:
404 self._write_method(method)
406 def _write_field(self, field):
407 if isinstance(field, Function):
408 self._write_method(field)
411 if isinstance(field, Callback):
412 self._write_callback(field)
415 attrs = [('name', field.name)]
416 # Fields are assumed to be read-only
417 # (see also girparser.c and generate.c)
418 if not field.readable:
419 attrs.append(('readable', '0'))
421 attrs.append(('writable', '1'))
423 attrs.append(('bits', str(field.bits)))
424 with self.tagcontext('field', attrs):
425 self._write_type(field.type)
427 def _write_signal(self, signal):
428 attrs = [('name', signal.name)]
430 attrs.append(('doc', signal.doc))
431 self._append_version(signal, attrs)
432 self._append_deprecated(signal, attrs)
433 with self.tagcontext('glib:signal', attrs):
434 self._write_return_type(signal.retval)
435 self._write_parameters(signal.parameters)