Change license name
[platform/upstream/gobject-introspection.git] / giscanner / girparser.py
1 # -*- Mode: Python -*-
2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008  Johan Dahlin
4 #
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.
9 #
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.
14 #
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.
19 #
20
21 import os
22
23 from collections import OrderedDict
24 from xml.etree.ElementTree import parse
25
26 from . import ast
27 from .girwriter import COMPATIBLE_GIR_VERSION
28 from .message import Position
29
30 CORE_NS = "http://www.gtk.org/introspection/core/1.0"
31 C_NS = "http://www.gtk.org/introspection/c/1.0"
32 GLIB_NS = "http://www.gtk.org/introspection/glib/1.0"
33
34
35 def _corens(tag):
36     return '{%s}%s' % (CORE_NS, tag)
37
38
39 def _glibns(tag):
40     return '{%s}%s' % (GLIB_NS, tag)
41
42
43 def _cns(tag):
44     return '{%s}%s' % (C_NS, tag)
45
46
47 class GIRParser(object):
48
49     def __init__(self, types_only=False):
50         self._types_only = types_only
51         self._namespace = None
52         self._filename_stack = []
53
54     # Public API
55
56     def parse(self, filename):
57         filename = os.path.abspath(filename)
58         self._filename_stack.append(filename)
59         tree = parse(filename)
60         self.parse_tree(tree)
61         self._filename_stack.pop()
62
63     def parse_tree(self, tree):
64         self._namespace = None
65         self._pkgconfig_packages = set()
66         self._includes = set()
67         self._c_includes = set()
68         self._c_prefix = None
69         self._parse_api(tree.getroot())
70
71     def get_namespace(self):
72         return self._namespace
73
74     # Private
75
76     def _find_first_child(self, node, name_or_names):
77         if isinstance(name_or_names, str):
78             for child in node:
79                 if child.tag == name_or_names:
80                     return child
81         else:
82             for child in node:
83                 if child.tag in name_or_names:
84                     return child
85         return None
86
87     def _find_children(self, node, name):
88         return [child for child in node if child.tag == name]
89
90     def _get_current_file(self):
91         if not self._filename_stack:
92             return None
93         cwd = os.getcwd() + os.sep
94         curfile = self._filename_stack[-1]
95         if curfile.startswith(cwd):
96             return curfile[len(cwd):]
97         return curfile
98
99     def _parse_api(self, root):
100         assert root.tag == _corens('repository')
101         version = root.attrib['version']
102         if version != COMPATIBLE_GIR_VERSION:
103             raise SystemExit("%s: Incompatible version %s (supported: %s)" %
104                              (self._get_current_file(), version, COMPATIBLE_GIR_VERSION))
105
106         for node in root:
107             if node.tag == _corens('include'):
108                 self._parse_include(node)
109             elif node.tag == _corens('package'):
110                 self._parse_pkgconfig_package(node)
111             elif node.tag == _cns('include'):
112                 self._parse_c_include(node)
113
114         ns = root.find(_corens('namespace'))
115         assert ns is not None
116         identifier_prefixes = ns.attrib.get(_cns('identifier-prefixes'))
117         if identifier_prefixes:
118             identifier_prefixes = identifier_prefixes.split(',')
119         symbol_prefixes = ns.attrib.get(_cns('symbol-prefixes'))
120         if symbol_prefixes:
121             symbol_prefixes = symbol_prefixes.split(',')
122         self._namespace = ast.Namespace(ns.attrib['name'],
123                                         ns.attrib['version'],
124                                         identifier_prefixes=identifier_prefixes,
125                                         symbol_prefixes=symbol_prefixes)
126         if 'shared-library' in ns.attrib:
127             self._namespace.shared_libraries = ns.attrib['shared-library'].split(',')
128         self._namespace.includes = self._includes
129         self._namespace.c_includes = self._c_includes
130         self._namespace.exported_packages = self._pkgconfig_packages
131
132         parser_methods = {
133             _corens('alias'): self._parse_alias,
134             _corens('bitfield'): self._parse_enumeration_bitfield,
135             _corens('callback'): self._parse_callback,
136             _corens('class'): self._parse_object_interface,
137             _corens('enumeration'): self._parse_enumeration_bitfield,
138             _corens('interface'): self._parse_object_interface,
139             _corens('record'): self._parse_record,
140             _corens('union'): self._parse_union,
141             _corens('docsection'): self._parse_doc_section,
142             _glibns('boxed'): self._parse_boxed}
143
144         if not self._types_only:
145             parser_methods[_corens('constant')] = self._parse_constant
146             parser_methods[_corens('function-macro')] = self._parse_function_macro
147             parser_methods[_corens('function')] = self._parse_function
148
149         for node in ns:
150             method = parser_methods.get(node.tag)
151             if method is not None:
152                 method(node)
153
154     def _parse_doc_section(self, node):
155         docsection = ast.DocSection(node.attrib["name"])
156         self._parse_generic_attribs(node, docsection)
157         self._namespace.append(docsection)
158
159     def _parse_include(self, node):
160         include = ast.Include(node.attrib['name'], node.attrib['version'])
161         self._includes.add(include)
162
163     def _parse_pkgconfig_package(self, node):
164         self._pkgconfig_packages.add(node.attrib['name'])
165
166     def _parse_c_include(self, node):
167         self._c_includes.add(node.attrib['name'])
168
169     def _parse_alias(self, node):
170         typeval = self._parse_type(node)
171         alias = ast.Alias(node.attrib['name'], typeval, node.attrib.get(_cns('type')))
172         self._parse_generic_attribs(node, alias)
173         self._namespace.append(alias)
174
175     def _parse_generic_attribs(self, node, obj):
176         assert isinstance(obj, ast.Annotated)
177         skip = node.attrib.get('skip')
178         if skip:
179             try:
180                 obj.skip = int(skip) > 0
181             except ValueError:
182                 obj.skip = False
183         introspectable = node.attrib.get('introspectable')
184         if introspectable:
185             try:
186                 obj.introspectable = int(introspectable) > 0
187             except ValueError:
188                 obj.introspectable = False
189         if self._types_only:
190             return
191         doc = node.find(_corens('doc'))
192         if doc is not None:
193             if doc.text:
194                 obj.doc = doc.text
195                 obj.doc_position = Position(doc.attrib.get('filename', '<unknown>'),
196                                             doc.attrib.get('line', None),
197                                             doc.attrib.get('column', None))
198         version = node.attrib.get('version')
199         if version:
200             obj.version = version
201         version_doc = node.find(_corens('doc-version'))
202         if version_doc is not None:
203             if version_doc.text:
204                 obj.version_doc = version_doc.text
205         deprecated = node.attrib.get('deprecated-version')
206         if deprecated:
207             obj.deprecated = deprecated
208         deprecated_doc = node.find(_corens('doc-deprecated'))
209         if deprecated_doc is not None:
210             if deprecated_doc.text:
211                 obj.deprecated_doc = deprecated_doc.text
212         stability = node.attrib.get('stability')
213         if stability:
214             obj.stability = stability
215         stability_doc = node.find(_corens('doc-stability'))
216         if stability_doc is not None:
217             if stability_doc.text:
218                 obj.stability_doc = stability_doc.text
219         attributes = node.findall(_corens('attribute'))
220         if attributes:
221             attributes_ = OrderedDict()
222             for attribute in attributes:
223                 name = attribute.attrib.get('name')
224                 value = attribute.attrib.get('value')
225                 attributes_[name] = value
226             obj.attributes = attributes_
227
228         if hasattr(obj, 'add_file_position'):
229             positions = sorted(node.findall(_corens('source-position')),
230                                key=lambda x: (x.attrib['filename'],
231                                               int(x.attrib['line'])))
232             for position in positions:
233                 if 'column' in position.attrib:
234                     column = int(position.attrib['column'])
235                 else:
236                     column = None
237
238                 obj.add_file_position(Position(position.attrib['filename'],
239                                                int(position.attrib['line']),
240                                                column))
241
242     def _parse_object_interface(self, node):
243         parent = node.attrib.get('parent')
244         if parent:
245             parent_type = self._namespace.type_from_name(parent)
246         else:
247             parent_type = None
248
249         ctor_kwargs = {'name': node.attrib['name'],
250                        'parent_type': parent_type,
251                        'gtype_name': node.attrib[_glibns('type-name')],
252                        'get_type': node.attrib[_glibns('get-type')],
253                        'c_symbol_prefix': node.attrib.get(_cns('symbol-prefix')),
254                        'ctype': node.attrib.get(_cns('type'))}
255         if node.tag == _corens('interface'):
256             klass = ast.Interface
257         elif node.tag == _corens('class'):
258             klass = ast.Class
259             is_abstract = node.attrib.get('abstract')
260             is_abstract = is_abstract and is_abstract != '0'
261             ctor_kwargs['is_abstract'] = is_abstract
262             is_final = node.attrib.get('final')
263             is_final = is_final and is_final != '0'
264             ctor_kwargs['is_final'] = is_final
265         else:
266             raise AssertionError(node)
267
268         obj = klass(**ctor_kwargs)
269         self._parse_generic_attribs(node, obj)
270         type_struct = node.attrib.get(_glibns('type-struct'))
271         if type_struct:
272             obj.glib_type_struct = self._namespace.type_from_name(type_struct)
273         if klass == ast.Class:
274             is_fundamental = node.attrib.get(_glibns('fundamental'))
275             if is_fundamental and is_fundamental != '0':
276                 obj.fundamental = True
277             for func_id in ['ref-func', 'unref-func',
278                             'set-value-func', 'get-value-func']:
279                 func_name = node.attrib.get(_glibns(func_id))
280                 obj.__dict__[func_id.replace('-', '_')] = func_name
281
282         if self._types_only:
283             self._namespace.append(obj)
284             return
285
286         for iface in self._find_children(node, _corens('implements')):
287             obj.interfaces.append(self._namespace.type_from_name(iface.attrib['name']))
288         for iface in self._find_children(node, _corens('prerequisite')):
289             obj.prerequisites.append(self._namespace.type_from_name(iface.attrib['name']))
290         for func_node in self._find_children(node, _corens('function')):
291             func = self._parse_function_common(func_node, ast.Function, obj)
292             obj.static_methods.append(func)
293         for method in self._find_children(node, _corens('method')):
294             func = self._parse_function_common(method, ast.Function, obj)
295             func.is_method = True
296             obj.methods.append(func)
297         for method in self._find_children(node, _corens('virtual-method')):
298             func = self._parse_function_common(method, ast.VFunction, obj)
299             self._parse_generic_attribs(method, func)
300             func.is_method = True
301             func.invoker = method.get('invoker')
302             obj.virtual_methods.append(func)
303         for ctor in self._find_children(node, _corens('constructor')):
304             func = self._parse_function_common(ctor, ast.Function, obj)
305             func.is_constructor = True
306             obj.constructors.append(func)
307         obj.fields.extend(self._parse_fields(node, obj))
308         for prop in self._find_children(node, _corens('property')):
309             obj.properties.append(self._parse_property(prop, obj))
310         for signal in self._find_children(node, _glibns('signal')):
311             obj.signals.append(self._parse_function_common(signal, ast.Signal, obj))
312
313         self._namespace.append(obj)
314
315     def _parse_callback(self, node):
316         callback = self._parse_function_common(node, ast.Callback)
317         self._namespace.append(callback)
318
319     def _parse_function(self, node):
320         function = self._parse_function_common(node, ast.Function)
321         self._namespace.append(function)
322
323     def _parse_function_macro(self, node):
324         name = node.attrib['name']
325         symbol = node.attrib.get(_cns('identifier'))
326         parameters = []
327         parameters_node = node.find(_corens('parameters'))
328         if (parameters_node is not None):
329             for paramnode in self._find_children(parameters_node, _corens('parameter')):
330                 param = ast.Parameter(paramnode.attrib.get('name'), None)
331                 parameters.append(param)
332                 self._parse_generic_attribs(paramnode, param)
333
334         func = ast.FunctionMacro(name, parameters, symbol)
335         self._parse_generic_attribs(node, func)
336
337         self._namespace.track(func)
338         self._namespace.append(func)
339
340     def _parse_parameter(self, node):
341         typeval = self._parse_type(node)
342         param = ast.Parameter(node.attrib.get('name'),
343                               typeval,
344                               node.attrib.get('direction') or ast.PARAM_DIRECTION_IN,
345                               node.attrib.get('transfer-ownership'),
346                               node.attrib.get('nullable') == '1',
347                               node.attrib.get('optional') == '1',
348                               node.attrib.get('allow-none') == '1',
349                               node.attrib.get('scope'),
350                               node.attrib.get('caller-allocates') == '1')
351         self._parse_generic_attribs(node, param)
352         return param
353
354     def _parse_function_common(self, node, klass, parent=None):
355         name = node.attrib['name']
356         returnnode = node.find(_corens('return-value'))
357         if not returnnode:
358             raise ValueError('node %r has no return-value' % (name, ))
359         transfer = returnnode.attrib.get('transfer-ownership')
360         nullable = returnnode.attrib.get('nullable') == '1'
361         retval = ast.Return(self._parse_type(returnnode), nullable, False, transfer)
362         self._parse_generic_attribs(returnnode, retval)
363         parameters = []
364
365         throws = (node.attrib.get('throws') == '1')
366
367         if klass is ast.Callback:
368             func = klass(name, retval, parameters, throws,
369                          node.attrib.get(_cns('type')))
370         elif klass is ast.Function:
371             identifier = node.attrib.get(_cns('identifier'))
372             func = klass(name, retval, parameters, throws, identifier)
373         elif klass is ast.VFunction:
374             func = klass(name, retval, parameters, throws)
375         elif klass is ast.Signal:
376             func = klass(name, retval, parameters,
377                          when=node.attrib.get('when'),
378                          no_recurse=node.attrib.get('no-recurse', '0') == '1',
379                          detailed=node.attrib.get('detailed', '0') == '1',
380                          action=node.attrib.get('action', '0') == '1',
381                          no_hooks=node.attrib.get('no-hooks', '0') == '1')
382         else:
383             assert False
384
385         func.set_property = node.attrib.get(_glibns('set-property'), None)
386         func.get_property = node.attrib.get(_glibns('get-property'), None)
387         func.shadows = node.attrib.get('shadows', None)
388         func.shadowed_by = node.attrib.get('shadowed-by', None)
389         func.moved_to = node.attrib.get('moved-to', None)
390         func.parent = parent
391
392         parameters_node = node.find(_corens('parameters'))
393         if (parameters_node is not None):
394             paramnode = self._find_first_child(parameters_node, _corens('instance-parameter'))
395             if paramnode:
396                 func.instance_parameter = self._parse_parameter(paramnode)
397             for paramnode in self._find_children(parameters_node, _corens('parameter')):
398                 parameters.append(self._parse_parameter(paramnode))
399             for i, paramnode in enumerate(self._find_children(parameters_node,
400                                                               _corens('parameter'))):
401                 param = parameters[i]
402                 self._parse_type_array_length(parameters, paramnode, param.type)
403                 closure = paramnode.attrib.get('closure')
404                 if closure:
405                     idx = int(closure)
406                     assert idx < len(parameters), "%d >= %d" % (idx, len(parameters))
407                     param.closure_name = parameters[idx].argname
408                 destroy = paramnode.attrib.get('destroy')
409                 if destroy:
410                     idx = int(destroy)
411                     assert idx < len(parameters), "%d >= %d" % (idx, len(parameters))
412                     param.destroy_name = parameters[idx].argname
413
414         self._parse_type_array_length(parameters, returnnode, retval.type)
415
416         # Re-set the function's parameters to notify it of changes to the list.
417         func.parameters = parameters
418
419         self._parse_generic_attribs(node, func)
420
421         self._namespace.track(func)
422         return func
423
424     def _parse_fields(self, node, obj):
425         res = []
426         names = (_corens('field'), _corens('record'), _corens('union'), _corens('callback'))
427         for child in node:
428             if child.tag in names:
429                 fieldobj = self._parse_field(child, obj)
430                 res.append(fieldobj)
431         return res
432
433     def _parse_compound(self, cls, node):
434         compound = cls(node.attrib.get('name'),
435                        ctype=node.attrib.get(_cns('type')),
436                        disguised=node.attrib.get('disguised') == '1',
437                        gtype_name=node.attrib.get(_glibns('type-name')),
438                        get_type=node.attrib.get(_glibns('get-type')),
439                        c_symbol_prefix=node.attrib.get(_cns('symbol-prefix')))
440         if node.attrib.get('foreign') == '1':
441             compound.foreign = True
442         self._parse_generic_attribs(node, compound)
443         if not self._types_only:
444             compound.fields.extend(self._parse_fields(node, compound))
445             for method in self._find_children(node, _corens('method')):
446                 func = self._parse_function_common(method, ast.Function, compound)
447                 func.is_method = True
448                 compound.methods.append(func)
449             for i, fieldnode in enumerate(self._find_children(node, _corens('field'))):
450                 field = compound.fields[i]
451                 self._parse_type_array_length(compound.fields, fieldnode, field.type)
452             for func in self._find_children(node, _corens('function')):
453                 compound.static_methods.append(
454                     self._parse_function_common(func, ast.Function, compound))
455             for ctor in self._find_children(node, _corens('constructor')):
456                 func = self._parse_function_common(ctor, ast.Function, compound)
457                 func.is_constructor = True
458                 compound.constructors.append(func)
459         return compound
460
461     def _parse_record(self, node, anonymous=False):
462         struct = self._parse_compound(ast.Record, node)
463         is_gtype_struct_for = node.attrib.get(_glibns('is-gtype-struct-for'))
464         if is_gtype_struct_for is not None:
465             struct.is_gtype_struct_for = self._namespace.type_from_name(is_gtype_struct_for)
466         if not anonymous:
467             self._namespace.append(struct)
468         return struct
469
470     def _parse_union(self, node, anonymous=False):
471         union = self._parse_compound(ast.Union, node)
472         if not anonymous:
473             self._namespace.append(union)
474         return union
475
476     def _parse_type_simple(self, typenode):
477         # ast.Fields can contain inline callbacks
478         if typenode.tag == _corens('callback'):
479             typeval = self._namespace.type_from_name(typenode.attrib['name'])
480             typeval.ctype = typenode.attrib.get(_cns('type'))
481             return typeval
482         # ast.Arrays have their own toplevel XML
483         elif typenode.tag == _corens('array'):
484             array_type = typenode.attrib.get('name')
485             element_type = self._parse_type(typenode)
486             array_ctype = typenode.attrib.get(_cns('type'))
487             ret = ast.Array(array_type, element_type, ctype=array_ctype)
488             # zero-terminated defaults to true...
489             zero = typenode.attrib.get('zero-terminated')
490             if zero and zero == '0':
491                 ret.zeroterminated = False
492             fixed_size = typenode.attrib.get('fixed-size')
493             if fixed_size:
494                 ret.size = int(fixed_size)
495
496             return ret
497         elif typenode.tag == _corens('varargs'):
498             return ast.Varargs()
499         elif typenode.tag == _corens('type'):
500             name = typenode.attrib.get('name')
501             ctype = typenode.attrib.get(_cns('type'))
502             if name is None:
503                 if ctype is None:
504                     return ast.TypeUnknown()
505                 return ast.Type(ctype=ctype)
506             elif name in ['GLib.List', 'GLib.SList']:
507                 subchild = self._find_first_child(typenode,
508                                                   list(map(_corens, ('callback', 'array',
509                                                                 '    varargs', 'type'))))
510                 if subchild is not None:
511                     element_type = self._parse_type(typenode)
512                 else:
513                     element_type = ast.TYPE_ANY
514                 return ast.List(name, element_type, ctype=ctype)
515             elif name == 'GLib.HashTable':
516                 subchildren = self._find_children(typenode, _corens('type'))
517                 subchildren_types = list(map(self._parse_type_simple, subchildren))
518                 while len(subchildren_types) < 2:
519                     subchildren_types.append(ast.TYPE_ANY)
520                 return ast.Map(subchildren_types[0], subchildren_types[1], ctype=ctype)
521             else:
522                 return self._namespace.type_from_name(name, ctype)
523         else:
524             assert False, "Failed to parse inner type"
525
526     def _parse_type(self, node):
527         for name in map(_corens, ('callback', 'array', 'varargs', 'type')):
528             typenode = node.find(name)
529             if typenode is not None:
530                 return self._parse_type_simple(typenode)
531         assert False, "Failed to parse toplevel type"
532
533     def _parse_type_array_length(self, siblings, node, typeval):
534         """A hack necessary to handle the integer parameter/field indexes on
535            array types."""
536         typenode = node.find(_corens('array'))
537         if typenode is None:
538             return
539         lenidx = typenode.attrib.get('length')
540         if lenidx is not None:
541             idx = int(lenidx)
542             assert idx < len(siblings), "%r %d >= %d" % (siblings, idx, len(siblings))
543             if isinstance(siblings[idx], ast.Field):
544                 typeval.length_param_name = siblings[idx].name
545             else:
546                 typeval.length_param_name = siblings[idx].argname
547
548     def _parse_boxed(self, node):
549         obj = ast.Boxed(node.attrib[_glibns('name')],
550                         gtype_name=node.attrib[_glibns('type-name')],
551                         get_type=node.attrib[_glibns('get-type')],
552                         c_symbol_prefix=node.attrib.get(_cns('symbol-prefix')))
553         self._parse_generic_attribs(node, obj)
554
555         if self._types_only:
556             self._namespace.append(obj)
557             return
558
559         for method in self._find_children(node, _corens('method')):
560             func = self._parse_function_common(method, ast.Function, obj)
561             func.is_method = True
562             obj.methods.append(func)
563         for ctor in self._find_children(node, _corens('constructor')):
564             obj.constructors.append(
565                 self._parse_function_common(ctor, ast.Function, obj))
566         for callback in self._find_children(node, _corens('callback')):
567             obj.fields.append(
568                 self._parse_function_common(callback, ast.Callback, obj))
569         self._namespace.append(obj)
570
571     def _parse_field(self, node, parent):
572         type_node = None
573         anonymous_node = None
574         if node.tag in map(_corens, ('callback', 'record', 'union')):
575             anonymous_elt = node
576         else:
577             anonymous_elt = self._find_first_child(node, _corens('callback'))
578         if anonymous_elt is not None:
579             if anonymous_elt.tag == _corens('callback'):
580                 anonymous_node = self._parse_function_common(anonymous_elt, ast.Callback)
581             elif anonymous_elt.tag == _corens('record'):
582                 anonymous_node = self._parse_record(anonymous_elt, anonymous=True)
583             elif anonymous_elt.tag == _corens('union'):
584                 anonymous_node = self._parse_union(anonymous_elt, anonymous=True)
585             else:
586                 assert False, anonymous_elt.tag
587         else:
588             assert node.tag == _corens('field'), node.tag
589             type_node = self._parse_type(node)
590         field = ast.Field(node.attrib.get('name'),
591                           type_node,
592                           node.attrib.get('readable') != '0',
593                           node.attrib.get('writable') == '1',
594                           node.attrib.get('bits'),
595                           anonymous_node=anonymous_node)
596         field.private = node.attrib.get('private') == '1'
597         field.parent = parent
598         self._parse_generic_attribs(node, field)
599         return field
600
601     def _parse_property(self, node, parent):
602         prop = ast.Property(node.attrib['name'],
603                             self._parse_type(node),
604                             node.attrib.get('readable') != '0',
605                             node.attrib.get('writable') == '1',
606                             node.attrib.get('construct') == '1',
607                             node.attrib.get('construct-only') == '1',
608                             node.attrib.get('transfer-ownership'))
609         prop.setter = node.attrib.get('setter')
610         prop.getter = node.attrib.get('getter')
611         prop.parent = parent
612         self._parse_generic_attribs(node, prop)
613         return prop
614
615     def _parse_member(self, node):
616         member = ast.Member(node.attrib['name'],
617                             node.attrib['value'],
618                             node.attrib.get(_cns('identifier')),
619                             node.attrib.get(_glibns('nick')),
620                             node.attrib.get(_glibns('name')))
621         self._parse_generic_attribs(node, member)
622         return member
623
624     def _parse_constant(self, node):
625         type_node = self._parse_type(node)
626         constant = ast.Constant(node.attrib['name'],
627                                 type_node,
628                                 node.attrib['value'],
629                                 node.attrib.get(_cns('type')))
630         self._parse_generic_attribs(node, constant)
631         self._namespace.append(constant)
632
633     def _parse_enumeration_bitfield(self, node):
634         name = node.attrib.get('name')
635         ctype = node.attrib.get(_cns('type'))
636         get_type = node.attrib.get(_glibns('get-type'))
637         type_name = node.attrib.get(_glibns('type-name'))
638         glib_error_domain = node.attrib.get(_glibns('error-domain'))
639         if node.tag == _corens('bitfield'):
640             klass = ast.Bitfield
641         else:
642             klass = ast.Enum
643         members = []
644         obj = klass(name, ctype,
645                     members=members,
646                     gtype_name=type_name,
647                     get_type=get_type)
648         obj.error_domain = glib_error_domain
649         obj.ctype = ctype
650         self._parse_generic_attribs(node, obj)
651
652         if self._types_only:
653             self._namespace.append(obj)
654             return
655
656         for member_node in self._find_children(node, _corens('member')):
657             member = self._parse_member(member_node)
658             member.parent = obj
659             members.append(member)
660         for func_node in self._find_children(node, _corens('function')):
661             func = self._parse_function_common(func_node, ast.Function)
662             func.parent = obj
663             obj.static_methods.append(func)
664         self._namespace.append(obj)