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(('c:type', enum.symbol))
245 with self.tagcontext('enumeration', attrs):
246 for member in enum.members:
247 self._write_member(member)
249 def _write_bitfield(self, bitfield):
250 attrs = [('name', bitfield.name)]
252 attrs.append(('doc', bitfield.doc))
253 self._append_version(bitfield, attrs)
254 self._append_deprecated(bitfield, attrs)
255 if isinstance(bitfield, GLibFlags):
256 attrs.extend([('glib:type-name', bitfield.type_name),
257 ('glib:get-type', bitfield.get_type),
258 ('c:type', bitfield.ctype)])
260 attrs.append(('c:type', bitfield.symbol))
261 with self.tagcontext('bitfield', attrs):
262 for member in bitfield.members:
263 self._write_member(member)
265 def _write_member(self, member):
266 attrs = [('name', member.name),
267 ('value', str(member.value)),
268 ('c:identifier', member.symbol)]
269 if isinstance(member, GLibEnumMember):
270 attrs.append(('glib:nick', member.nick))
271 self.write_tag('member', attrs)
273 def _write_constant(self, constant):
274 attrs = [('name', constant.name),
275 ('value', str(constant.value))]
276 with self.tagcontext('constant', attrs):
277 self._write_type(constant.type)
279 def _write_class(self, node):
280 attrs = [('name', node.name),
281 ('c:type', node.ctype)]
283 attrs.append(('doc', node.doc))
284 self._append_version(node, attrs)
285 self._append_deprecated(node, attrs)
286 if isinstance(node, Class):
288 if node.parent is not None:
289 attrs.append(('parent', node.parent))
291 attrs.append(('abstract', '1'))
293 tag_name = 'interface'
294 if isinstance(node, (GLibObject, GLibInterface)):
295 attrs.append(('glib:type-name', node.type_name))
297 attrs.append(('glib:get-type', node.get_type))
298 with self.tagcontext(tag_name, attrs):
299 if isinstance(node, GLibObject):
300 for iface in node.interfaces:
301 self.write_tag('implements', [('name', iface)])
302 if isinstance(node, Interface):
303 for iface in node.prerequisites:
304 self.write_tag('prerequisite', [('name', iface)])
305 if isinstance(node, Class):
306 for method in node.constructors:
307 self._write_constructor(method)
308 for method in node.static_methods:
309 self._write_static_method(method)
310 for method in node.methods:
311 self._write_method(method)
312 for prop in node.properties:
313 self._write_property(prop)
314 for field in node.fields:
315 self._write_field(field)
316 for signal in node.signals:
317 self._write_signal(signal)
319 def _write_boxed(self, boxed):
320 attrs = [('c:type', boxed.ctype),
321 ('glib:name', boxed.name)]
323 attrs.append(('doc', boxed.doc))
324 attrs.extend(self._boxed_attrs(boxed))
325 with self.tagcontext('glib:boxed', attrs):
326 for method in boxed.constructors:
327 self._write_constructor(method)
328 for method in boxed.methods:
329 self._write_method(method)
331 def _write_property(self, prop):
332 attrs = [('name', prop.name)]
333 self._append_version(prop, attrs)
334 self._append_deprecated(prop, attrs)
335 # Properties are assumed to be readable (see also generate.c)
336 if not prop.readable:
337 attrs.append(('readable', '0'))
339 attrs.append(('writable', '1'))
341 attrs.append(('construct', '1'))
342 if prop.construct_only:
343 attrs.append(('construct-only', '1'))
345 attrs.append(('doc', prop.doc))
346 with self.tagcontext('property', attrs):
347 self._write_type(prop.type)
349 def _write_callback(self, callback):
350 # FIXME: reuse _write_function
351 attrs = [('name', callback.name), ('c:type', callback.ctype)]
353 attrs.append(('doc', callback.doc))
354 self._append_version(callback, attrs)
355 self._append_deprecated(callback, attrs)
356 self._append_throws(callback, attrs)
357 with self.tagcontext('callback', attrs):
358 self._write_return_type(callback.retval)
359 self._write_parameters(callback.parameters)
361 def _boxed_attrs(self, boxed):
362 return [('glib:type-name', boxed.type_name),
363 ('glib:get-type', boxed.get_type)]
365 def _write_record(self, record):
366 attrs = [('name', record.name),
367 ('c:type', record.symbol)]
369 attrs.append(('disguised', '1'))
371 attrs.append(('doc', record.doc))
372 self._append_version(record, attrs)
373 self._append_deprecated(record, attrs)
374 if isinstance(record, GLibBoxed):
375 attrs.extend(self._boxed_attrs(record))
376 with self.tagcontext('record', attrs):
378 for field in record.fields:
379 self._write_field(field)
380 for method in record.constructors:
381 self._write_constructor(method)
382 for method in record.methods:
383 self._write_method(method)
385 def _write_union(self, union):
386 attrs = [('name', union.name),
387 ('c:type', union.symbol)]
389 attrs.append(('doc', union.doc))
390 self._append_version(union, attrs)
391 self._append_deprecated(union, attrs)
392 if isinstance(union, GLibBoxed):
393 attrs.extend(self._boxed_attrs(union))
394 with self.tagcontext('union', attrs):
396 for field in union.fields:
397 self._write_field(field)
398 for method in union.constructors:
399 self._write_constructor(method)
400 for method in union.methods:
401 self._write_method(method)
403 def _write_field(self, field):
404 if isinstance(field, Function):
405 self._write_method(field)
408 if isinstance(field, Callback):
409 self._write_callback(field)
412 attrs = [('name', field.name)]
413 # Fields are assumed to be read-only
414 # (see also girparser.c and generate.c)
415 if not field.readable:
416 attrs.append(('readable', '0'))
418 attrs.append(('writable', '1'))
420 attrs.append(('bits', str(field.bits)))
421 with self.tagcontext('field', attrs):
422 self._write_type(field.type)
424 def _write_signal(self, signal):
425 attrs = [('name', signal.name)]
427 attrs.append(('doc', signal.doc))
428 self._append_version(signal, attrs)
429 self._append_deprecated(signal, attrs)
430 with self.tagcontext('glib:signal', attrs):
431 self._write_return_type(signal.retval)
432 self._write_parameters(signal.parameters)