6 from .odict import odict
7 from .treebuilder import (Callback, Class, Enum, Function, Interface,
8 Member, Property, Struct)
10 # Copied from h2defs.py
11 _upperstr_pat1 = re.compile(r'([^A-Z])([A-Z])')
12 _upperstr_pat2 = re.compile(r'([A-Z][A-Z])([A-Z][0-9a-z])')
13 _upperstr_pat3 = re.compile(r'^([A-Z])([A-Z])')
15 def to_underscores(name):
16 """Converts a typename to the equivalent underscores name.
17 This is used to form the type conversion macros and enum/flag
19 name = _upperstr_pat1.sub(r'\1_\2', name)
20 name = _upperstr_pat2.sub(r'\1_\2', name)
21 name = _upperstr_pat3.sub(r'\1_\2', name, count=1)
24 _libtool_pat = re.compile("dlname='([A-z0-9\.]+)'\n")
26 def resolve_libtool(libname):
27 data = open(libname).read()
28 filename = _libtool_pat.search(data).groups()[0]
29 libname = os.path.join(os.path.dirname(libname),
35 def __init__(self, name, members, type_name, get_type):
36 Enum.__init__(self, name, members)
37 self.type_name = type_name
38 self.get_type = get_type
41 return '%s(%r, %r, %r)' % (
42 self.__class__.__name__,
48 class GLibFlags(GLibEnum):
52 class GLibEnumMember(Member):
53 def __init__(self, name, value, nick):
54 Member.__init__(self, name, value)
58 class GLibObject(Class):
59 def __init__(self, name, parent, type_name, get_type):
60 Class.__init__(self, name, parent)
61 self.type_name = type_name
62 self.get_type = get_type
65 class GLibBoxed(Struct):
66 def __init__(self, name, type_name, get_type):
67 Struct.__init__(self, name)
68 self.constructors = []
70 self.type_name = type_name
71 self.get_type = get_type
74 class GLibInterface(Interface):
75 def __init__(self, name, type_name, get_type):
76 Interface.__init__(self, name)
77 self.type_name = type_name
78 self.get_type = get_type
81 class GLibProperty(Property):
85 class GObjectTreeBuilder(object):
86 def __init__(self, namespace_name):
87 self._namespace_name = namespace_name
88 self._output_ns = odict()
95 return self._output_ns.values()
97 def load_library(self, libname):
98 if libname.endswith('.la'):
99 libname = resolve_libtool(libname)
100 self._library = ctypes.cdll.LoadLibrary(libname)
102 def parse(self, nodes):
104 self._parse_node(node)
106 def register_include(self, filename):
107 from .gidlparser import GIDLParser
108 parser = GIDLParser(filename)
109 nsname = parser.get_namespace_name()
110 for node in parser.get_nodes():
111 self._type_names[node.type_name] = (nsname, node)
115 def _add_attribute(self, node, replace=False):
116 node_name = node.name
117 if node_name in self._output_ns and not replace:
119 self._output_ns[node_name] = node
121 def _remove_attribute(self, name):
122 del self._output_ns[name]
124 def _get_attribute(self, name):
125 return self._output_ns.get(name)
127 def _register_internal_type(self, type_name, node):
128 self._type_names[type_name] = (None, node)
130 def _strip_namespace_func(self, name):
132 prefix = self._namespace_name.lower() + '_'
134 if name.startswith(prefix):
135 name = orig_name[len(prefix):]
138 def _strip_namespace_object(self, name):
140 prefix = self._namespace_name.lower()
142 if name.startswith(prefix):
143 name = orig_name[len(prefix):]
146 def _resolve_type_name(self, type_name):
147 item = self._type_names.get(type_name)
152 return '%s.%s' % (nsname, item.name)
155 def _resolve_param_type(self, ptype):
156 type_name = ptype.replace('*', '')
157 resolved_type_name = self._resolve_type_name(type_name)
158 if type_name != resolved_type_name:
159 return ptype.replace(type_name, resolved_type_name)
162 def _parse_node(self, node):
163 if isinstance(node, Enum):
164 self._parse_enum(node)
165 elif isinstance(node, Function):
166 self._parse_function(node)
167 elif isinstance(node, Struct):
168 self._parse_struct(node)
169 elif isinstance(node, Callback):
170 self._parse_callback(node)
172 print 'GOBJECT BUILDER: Unhandled node:', node
174 def _parse_enum(self, enum):
175 enum.name = self._strip_namespace_object(enum.name)
176 self._add_attribute(enum)
178 def _parse_function(self, func):
179 if self._parse_get_type_function(func):
181 elif self._parse_constructor(func):
183 elif self._parse_method(func):
186 self._parse_parameters(func.parameters)
187 func.retval.type = self._resolve_param_type(func.retval.type)
189 func.name = self._strip_namespace_func(func.name)
190 self._add_attribute(func)
192 def _parse_parameters(self, parameters):
193 for parameter in parameters:
194 parameter.type = self._resolve_param_type(parameter.type)
196 def _parse_get_type_function(self, func):
197 # GType *_get_type(void)
199 if not symbol.endswith('_get_type'):
201 if func.retval.type != 'GType':
206 func = getattr(self._library, symbol)
207 func.restype = cgobject.GType
210 self._introspect_type(type_id, symbol)
213 def _parse_method(self, func):
214 if not func.parameters:
217 # FIXME: This is hackish, we should preserve the pointer structures
218 # here, so we can find pointers to objects and not just
219 # pointers to anything
220 first_arg = func.parameters[0].type
221 if first_arg.count('*') != 1:
224 object_name = first_arg.replace('*', '')
225 return self._parse_method_common(func, object_name, is_method=True)
227 def _parse_constructor(self, func):
228 # FIXME: This is hackish, we should preserve the pointer structures
229 # here, so we can find pointers to objects and not just
230 # pointers to anything
231 rtype = func.retval.type
232 if rtype.count('*') != 1:
235 object_name = rtype.replace('*', '')
236 return self._parse_method_common(func, object_name, is_method=False)
238 def _parse_method_common(self, func, object_name, is_method):
239 orig_name = object_name
240 if object_name.lower().startswith(self._namespace_name.lower()):
241 object_name = object_name[len(self._namespace_name):]
242 class_ = self._get_attribute(object_name)
243 if class_ is None or not isinstance(class_, (GLibObject, GLibBoxed)):
246 # GtkButton -> gtk_button_, so we can figure out the method name
247 prefix = to_underscores(orig_name).lower() + '_'
248 if not func.name.startswith(prefix):
251 # Strip namespace and object prefix: gtk_window_new -> new
252 func.name = func.name[len(prefix):]
254 class_.methods.append(func)
256 class_.constructors.append(func)
257 self._parse_parameters(func.parameters)
258 func.retval.type = self._resolve_param_type(func.retval.type)
261 def _parse_struct(self, struct):
262 if (struct.name.startswith('_') or
263 struct.name.endswith('Iface') or
264 struct.name.endswith('Class')):
266 self._add_attribute(struct)
268 def _parse_callback(self, callback):
269 self._add_attribute(callback)
271 def _introspect_type(self, type_id, symbol):
272 fundamental_type_id = cgobject.type_fundamental(type_id)
273 if (fundamental_type_id == cgobject.TYPE_ENUM or
274 fundamental_type_id == cgobject.TYPE_FLAGS):
275 self._introspect_enum(fundamental_type_id, type_id, symbol)
276 elif fundamental_type_id == cgobject.TYPE_OBJECT:
277 self._introspect_object(type_id, symbol)
278 elif fundamental_type_id == cgobject.TYPE_INTERFACE:
279 self._introspect_interface(type_id, symbol)
280 elif fundamental_type_id == cgobject.TYPE_BOXED:
281 self._introspect_boxed(type_id, symbol)
283 print 'unhandled GType: %s' % (cgobject.type_name(type_id),)
285 def _introspect_enum(self, ftype_id, type_id, symbol):
286 type_class = cgobject.type_class_ref(type_id)
287 if type_class is None:
291 for enum_value in type_class.get_values():
292 members.append(GLibEnumMember(enum_value.value_name,
294 enum_value.value_nick))
296 klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
297 type_name = cgobject.type_name(type_id)
298 node = klass(self._strip_namespace_object(type_name),
299 members, type_name, symbol)
300 self._add_attribute(node, replace=True)
301 self._register_internal_type(type_name, node)
303 def _introspect_object(self, type_id, symbol):
304 type_name = cgobject.type_name(type_id)
305 parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
306 node = GLibObject(self._strip_namespace_object(type_name),
307 self._resolve_type_name(parent_type_name),
309 self._introspect_properties(node, type_id)
310 self._add_attribute(node)
311 self._remove_attribute(type_name)
312 self._register_internal_type(type_name, node)
314 def _introspect_interface(self, type_id, symbol):
315 type_name = cgobject.type_name(type_id)
316 node = GLibInterface(self._strip_namespace_object(type_name),
318 self._introspect_properties(node, type_id)
319 self._add_attribute(node)
320 self._remove_attribute(type_name)
321 self._register_internal_type(type_name, node)
323 def _introspect_boxed(self, type_id, symbol):
324 type_name = cgobject.type_name(type_id)
325 node = GLibBoxed(self._strip_namespace_object(type_name),
327 self._add_attribute(node)
328 self._remove_attribute(type_name)
329 self._register_internal_type(type_name, node)
331 def _introspect_properties(self, node, type_id):
332 fundamental_type_id = cgobject.type_fundamental(type_id)
333 if fundamental_type_id == cgobject.TYPE_OBJECT:
334 pspecs = cgobject.object_class_list_properties(type_id)
335 elif fundamental_type_id == cgobject.TYPE_INTERFACE:
336 pspecs = cgobject.object_interface_list_properties(type_id)
341 if pspec.owner_type != type_id:
343 node.properties.append(Property(
345 cgobject.type_name(pspec.value_type)))