2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008 Johan Dahlin
5 # This program is free software; you can redistribute it and/or
6 # modify it under the terms of the GNU General Public License
7 # as published by the Free Software Foundation; either version 2
8 # of the License, or (at your option) any later version.
10 # This program 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
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program; if not, write to the Free Software
17 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 from xml.etree.cElementTree import parse
23 from .ast import (Alias, Array, Callback, Enum, Function, Field, Namespace,
24 Parameter, Property, Return, Union, Struct, Type, Varargs)
25 from .glibast import (GLibEnum, GLibEnumMember, GLibFlags,
26 GLibInterface, GLibObject, GLibBoxedStruct,
27 GLibBoxedUnion, GLibBoxedOther)
29 CORE_NS = "http://www.gtk.org/introspection/core/1.0"
30 C_NS = "http://www.gtk.org/introspection/c/1.0"
31 GLIB_NS = "http://www.gtk.org/introspection/glib/1.0"
35 return '{%s}%s' % (CORE_NS, tag)
39 return '{%s}%s' % (GLIB_NS, tag)
43 return '{%s}%s' % (C_NS, tag)
46 class GIRParser(object):
48 def __init__(self, filename, initial_parse=True):
49 self._includes = set()
50 self._namespace = None
51 self._shared_libraries = []
52 self._tree = parse(filename)
60 self._includes.clear()
62 del self._shared_libraries[:]
64 self._parse_api(self._tree.getroot())
66 def get_namespace(self):
67 return self._namespace
69 def get_shared_libraries(self):
70 return self._shared_libraries
72 def get_includes(self):
80 def _add_node(self, node):
81 self._namespace.nodes.append(node)
83 def _parse_api(self, root):
84 assert root.tag == _corens('repository')
85 for node in root.getchildren():
86 if node.tag == _corens('include'):
87 self._includes.add((node.attrib['name']))
88 ns = root.find(_corens('namespace'))
90 self._namespace = Namespace(ns.attrib['name'], ns.attrib['version'])
91 self._shared_libraries.extend(ns.attrib['shared-library'].split(','))
92 for child in ns.getchildren():
93 self._parse_node(child)
95 def _parse_node(self, node):
96 if node.tag == _corens('alias'):
97 self._add_node(self._parse_alias(node))
98 elif node.tag in [_corens('callback')]:
99 self._add_node(self._parse_function(node, Callback))
100 elif node.tag in [_corens('function')]:
101 self._add_node(self._parse_function(node, Function))
102 elif node.tag in [_corens('class'),
103 _corens('interface')]:
104 self._parse_object_interface(node)
105 elif node.tag == _corens('record'):
106 self._parse_struct(node)
107 elif node.tag == _corens('union'):
108 self._parse_union(node)
109 elif node.tag == _glibns('boxed'):
110 self._parse_boxed(node)
111 elif node.tag in [_corens('enumeration'),
112 _corens('bitfield')]:
113 self._parse_enumeration_bitfield(node)
115 def _parse_alias(self, node):
116 return Alias(node.attrib['name'],
117 node.attrib['target'],
118 node.attrib.get(_cns('type')))
120 def _parse_object_interface(self, node):
121 if node.tag == _corens('interface'):
122 klass = GLibInterface
123 elif node.tag == _corens('class'):
126 raise AssertionError(node)
128 obj = klass(node.attrib['name'],
129 node.attrib.get('parent'),
130 node.attrib[_glibns('type-name')],
131 node.attrib[_glibns('get-type')],
132 node.attrib.get(_cns('type')))
133 for iface in node.findall(_corens('implements')):
134 obj.interfaces.append(iface.attrib['name'])
135 for method in node.findall(_corens('method')):
136 obj.methods.append(self._parse_function(method, Function))
137 for ctor in node.findall(_corens('constructor')):
138 obj.constructors.append(self._parse_function(ctor, Function))
139 for callback in node.findall(_corens('callback')):
140 obj.fields.append(self._parse_function(callback, Callback))
141 for field in node.findall(_corens('field')):
142 obj.fields.append(self._parse_field(field))
143 for property in node.findall(_corens('property')):
144 obj.properties.append(self._parse_property(property))
145 for signal in node.findall(_glibns('signal')):
146 obj.signals.append(self._parse_function(signal, Function))
149 def _parse_function(self, node, klass):
150 name = node.attrib['name']
151 returnnode = node.find(_corens('return-value'))
153 raise ValueError('node %r has no return-value' % (name, ))
154 transfer = returnnode.attrib.get('transfer-ownership')
155 retval = Return(self._parse_type(returnnode), transfer)
156 parameters_node = node.find(_corens('parameters'))
158 if (parameters_node is not None):
159 for paramnode in parameters_node.findall(_corens('parameter')):
160 parameters.append(Parameter(paramnode.attrib.get('name'),
161 self._parse_type(paramnode)))
162 if klass is Callback:
163 return klass(name, retval, parameters,
164 node.attrib.get(_cns('type')))
166 identifier = node.attrib.get(_cns('identifier'))
167 return klass(name, retval, parameters, identifier)
169 def _parse_struct(self, node):
170 if _glibns('type-name') in node.attrib:
171 struct = GLibBoxedStruct(node.attrib['name'],
172 node.attrib[_glibns('type-name')],
173 node.attrib[_glibns('get-type')],
174 node.attrib.get(_cns('type')))
176 struct = Struct(node.attrib['name'],
177 node.attrib.get(_cns('type')))
178 for field in node.findall(_corens('field')):
179 struct.fields.append(self._parse_field(field))
180 for callback in node.findall(_corens('callback')):
181 struct.fields.append(self._parse_function(callback, Callback))
182 for method in node.findall(_corens('method')):
183 struct.fields.append(self._parse_function(method, Function))
184 for ctor in node.findall(_corens('constructor')):
185 struct.constructors.append(self._parse_function(ctor, Function))
186 self._add_node(struct)
188 def _parse_union(self, node):
189 if _glibns('type-name') in node.attrib:
190 struct = GLibBoxedUnion(node.attrib['name'],
191 node.attrib[_glibns('type-name')],
192 node.attrib[_glibns('get-type')],
193 node.attrib.get(_cns('type')))
195 struct = Union(node.attrib['name'],
196 node.attrib.get(_cns('type')))
197 for callback in node.findall(_corens('callback')):
198 struct.fields.append(self._parse_function(callback, Callback))
199 for field in node.findall(_corens('field')):
200 struct.fields.append(self._parse_field(field))
201 for method in node.findall(_corens('method')):
202 struct.fields.append(self._parse_function(method, Function))
203 for ctor in node.findall(_corens('constructor')):
204 struct.constructors.append(self._parse_function(ctor, Function))
205 self._add_node(struct)
207 def _parse_type(self, node):
208 typenode = node.find(_corens('type'))
209 if typenode is not None:
210 return Type(typenode.attrib['name'],
211 typenode.attrib.get(_cns('type')))
212 typenode = node.find(_corens('array'))
213 if typenode is not None:
214 return Array(typenode.attrib.get(_cns('type')),
215 self._parse_type(typenode))
216 typenode = node.find(_corens('varargs'))
217 if typenode is not None:
219 raise ValueError("Couldn't parse type of node %r; children=%r",
222 def _parse_boxed(self, node):
223 obj = GLibBoxedOther(node.attrib[_glibns('name')],
224 node.attrib[_glibns('type-name')],
225 node.attrib[_glibns('get-type')])
226 for method in node.findall(_corens('method')):
227 obj.methods.append(self._parse_function(method, Function))
228 for ctor in node.findall(_corens('constructor')):
229 obj.constructors.append(self._parse_function(ctor, Function))
230 for callback in node.findall(_corens('callback')):
231 obj.fields.append(self._parse_function(callback, Callback))
234 def _parse_field(self, node):
235 type_node = self._parse_type(node)
236 return Field(node.attrib['name'],
240 def _parse_property(self, node):
241 type_node = self._parse_type(node)
242 return Property(node.attrib['name'],
244 node.attrib.get('readable') != '0',
245 node.attrib.get('writable') == '1',
246 node.attrib.get('construct') == '1',
247 node.attrib.get('construct-only') == '1',
250 def _parse_member(self, node):
251 return GLibEnumMember(node.attrib['name'],
252 node.attrib['value'],
253 node.attrib.get(_cns('identifier')),
254 node.attrib.get(_glibns('nick')))
256 def _parse_enumeration_bitfield(self, node):
257 name = node.attrib.get('name')
258 ctype = node.attrib.get(_cns('type'))
259 get_type = node.attrib.get(_glibns('get-type'))
260 type_name = node.attrib.get(_glibns('type-name'))
262 if node.tag == _corens('bitfield'):
270 for member in node.findall(_corens('member')):
271 members.append(self._parse_member(member))
274 obj = klass(name, type_name, members)
276 obj = klass(name, type_name, members, get_type)