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.
24 from ctypes.util import find_library
26 from . import cgobject
27 from .ast import (Callback, Constant, Enum, Function, Member, Namespace,
28 Parameter, Property, Return, Struct, Type, Alias,
29 Union, Field, type_name_from_ctype,
30 default_array_types, TYPE_UINT8, PARAM_DIRECTION_IN)
31 from .transformer import Names
32 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
33 GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
34 GLibBoxedUnion, GLibBoxedOther, type_names)
35 from .utils import extract_libtool, to_underscores, to_underscores_noprefix
37 default_array_types['guchar*'] = TYPE_UINT8
40 # These ones break GError conventions
41 'g_simple_async_result_new_from_error',
42 'g_simple_async_result_set_from_error',
43 'g_simple_async_result_propagate_error',
44 'g_simple_async_result_report_error_in_idle',
45 'gtk_print_operation_get_error',
48 SYMBOL_BLACKLIST_RE = [re.compile(x) for x in \
49 [r'\w+_marshal_[A-Z]+__', ]]
52 class Unresolved(object):
54 def __init__(self, target):
58 class UnknownTypeError(Exception):
62 class GLibTransformer(object):
64 def __init__(self, transformer, noclosure=False):
65 self._transformer = transformer
66 self._transformer.set_container_types(['GList*', 'GSList*'],
68 self._namespace_name = None
70 self._uscore_type_names = {}
72 self._failed_types = {}
73 self._boxed_types = {}
74 self._private_internal_types = {}
75 self._noclosure = noclosure
76 self._validating = False
80 def add_library(self, libname):
82 libtool_libname = 'lib' + libname + '.la'
83 if os.path.exists(libname):
84 found_libname = os.path.abspath(libname)
85 elif os.path.exists(libtool_libname):
86 found_libname = extract_libtool(libtool_libname)
87 libname = os.path.basename(found_libname)
89 found_libname = find_library(libname)
91 if libname.endswith('.la'):
92 found_libname = extract_libtool(libname)
93 libname = os.path.basename(found_libname)
95 raise ValueError("Failed to find library: %r" % (libname, ))
96 self._libraries.append(ctypes.cdll.LoadLibrary(found_libname))
99 def _print_statistics(self):
100 nodes = list(self._names.names.itervalues())
102 def count_type(otype):
103 return len([x for x in nodes
104 if isinstance(x[1], otype)])
105 objectcount = count_type(GLibObject)
106 ifacecount = count_type(GLibInterface)
107 enumcount = count_type(GLibEnum)
108 print " %d nodes; %d objects, %d interfaces, %d enums" \
109 % (len(nodes), objectcount, ifacecount, enumcount)
112 namespace = self._transformer.parse()
113 self._namespace_name = namespace.name
115 # First pass: parsing
116 for node in namespace.nodes:
117 self._parse_node(node)
119 # We don't want an alias for this - it's handled specially in
120 # the typelib compiler.
121 if namespace.name == 'GObject':
122 del self._names.aliases['Type']
124 # Introspection is done from within parsing
126 # Second pass: pair boxed structures
127 for boxed in self._boxed_types.itervalues():
128 self._pair_boxed_type(boxed)
129 # Third pass: delete class structures, resolve
130 # all types we now know about
131 nodes = list(self._names.names.itervalues())
132 for (ns, node) in nodes:
134 self._resolve_node(node)
136 print "WARNING: DELETING node %s: %s" % (node.name, e)
137 self._remove_attribute(node.name)
138 # associate GtkButtonClass with GtkButton
139 if isinstance(node, Struct):
140 self._pair_class_struct(node)
141 for (ns, alias) in self._names.aliases.itervalues():
142 self._resolve_alias(alias)
144 self._print_statistics()
145 # Fourth pass: ensure all types are known
146 if not self._noclosure:
147 self._validate(nodes)
149 # Create a new namespace with what we found
150 namespace = Namespace(namespace.name, namespace.version)
151 namespace.nodes = map(lambda x: x[1], self._names.aliases.itervalues())
152 for (ns, x) in self._names.names.itervalues():
153 namespace.nodes.append(x)
158 def _add_attribute(self, node, replace=False):
159 node_name = node.name
160 if (not replace) and node_name in self._names.names:
162 self._names.names[node_name] = (None, node)
164 def _remove_attribute(self, name):
165 del self._names.names[name]
167 def _get_attribute(self, name):
168 node = self._names.names.get(name)
173 def _register_internal_type(self, type_name, node):
174 self._names.type_names[type_name] = (None, node)
175 uscored = to_underscores(type_name).lower()
176 self._uscore_type_names[uscored] = node
177 # Besides the straight underscore conversion, we also try
178 # removing the underscores from the namespace as a possible C
179 # mapping; e.g. it's webkit_web_view, not web_kit_web_view
180 suffix = self._transformer.remove_prefix(type_name)
181 prefix = type_name[:-len(suffix)]
182 no_uscore_prefixed = (prefix + '_' + to_underscores(suffix)).lower()
183 self._uscore_type_names[no_uscore_prefixed] = node
187 def _type_from_gtype(self, type_id):
188 ctype = cgobject.type_name(type_id)
189 type_name = type_name_from_ctype(ctype)
190 type_name = type_name.replace('*', '')
191 type_name = self._resolve_type_name(type_name)
193 type = Type(type_name, ctype)
194 type._gtype = type_id
197 def _resolve_gtypename(self, gtype_name):
199 return self._transformer.gtypename_to_giname(gtype_name,
202 return Unresolved(gtype_name)
204 def _create_gobject(self, node):
205 type_name = 'G' + node.name
206 if type_name == 'GObject':
210 type_id = cgobject.type_from_name(type_name)
211 parent_type_name = cgobject.type_name(
212 cgobject.type_parent(type_id))
213 parent_gitype = self._resolve_gtypename(parent_type_name)
214 symbol = to_underscores(type_name).lower() + '_get_type'
215 node = GLibObject(node.name, parent_gitype, type_name, symbol, True)
216 type_id = cgobject.TYPE_OBJECT
217 self._introspect_properties(node, type_id)
218 self._introspect_signals(node, type_id)
219 self._add_attribute(node)
220 self._register_internal_type(type_name, node)
224 def _parse_node(self, node):
225 if isinstance(node, Enum):
226 self._parse_enum(node)
227 elif isinstance(node, Function):
228 self._parse_function(node)
229 elif isinstance(node, Struct):
230 self._parse_struct(node)
231 elif isinstance(node, Callback):
232 self._parse_callback(node)
233 elif isinstance(node, Alias):
234 self._parse_alias(node)
235 elif isinstance(node, Member):
236 # FIXME: atk_misc_instance singletons
238 elif isinstance(node, Union):
239 self._parse_union(node)
240 elif isinstance(node, Constant):
241 self._parse_constant(node)
243 print 'GLIB Transformer: Unhandled node:', node
245 def _parse_alias(self, alias):
246 self._names.aliases[alias.name] = (None, alias)
248 def _parse_enum(self, enum):
249 self._add_attribute(enum)
251 def _parse_constant(self, constant):
252 self._add_attribute(constant)
254 def _parse_function(self, func):
255 if func.symbol in SYMBOL_BLACKLIST:
257 if func.symbol.startswith('_'):
259 for regexp in SYMBOL_BLACKLIST_RE:
260 if regexp.match(func.symbol):
262 if self._parse_get_type_function(func):
265 self._add_attribute(func)
267 def _parse_get_type_function(self, func):
269 if not symbol.endswith('_get_type'):
271 if self._namespace_name == 'GLib':
272 # No GObjects in GLib
276 # GType *_get_type(void)
277 if func.retval.type.name not in ['Type',
281 print ("Warning: *_get_type function returns '%r'"
282 ", not GObject.Type") % (func.retval.type.name, )
285 if not self._libraries:
286 print "Warning: No libraries loaded, cannot call %s" % (symbol, )
289 for library in self._libraries:
291 func = getattr(library, symbol)
293 except AttributeError:
296 print 'Warning: could not find symbol: %s' % symbol
297 name = symbol.replace('_get_type', '')
298 self._failed_types[name] = True
301 func.restype = cgobject.GType
304 self._introspect_type(type_id, symbol)
307 def _name_is_internal_gtype(self, giname):
309 node = self._get_attribute(giname)
310 return isinstance(node, (GLibObject, GLibInterface,
311 GLibBoxed, GLibEnum, GLibFlags))
315 def _parse_method(self, func):
316 if not func.parameters:
318 return self._parse_method_common(func, True)
320 def _parse_constructor(self, func):
321 return self._parse_method_common(func, False)
323 def _parse_method_common(self, func, is_method):
324 # Skip _get_type functions, we processed them
326 if func.symbol.endswith('_get_type'):
328 if self._namespace_name == 'GLib':
329 # No GObjects in GLib
333 target_arg = func.retval
335 target_arg = func.parameters[0]
338 # Methods require their first arg to be a known class
339 # Look at the original C type (before namespace stripping), without
340 # pointers: GtkButton -> gtk_button_, so we can figure out the
342 argtype = target_arg.type.ctype.replace('*', '')
343 name = self._transformer.remove_prefix(argtype)
344 name_uscore = to_underscores_noprefix(name).lower()
345 name_offset = func.symbol.find(name_uscore)
348 prefix = func.symbol[:name_offset+len(name_uscore)]
350 # Constructors must have _new
351 # Take everything before that as class name
352 new_idx = func.symbol.find('_new')
355 # Constructors don't return basic types
356 derefed = self._transformer.follow_aliases(target_arg.type.name,
358 if derefed in type_names:
359 #print "NOTE: Rejecting constructor returning basic: %r" \
362 prefix = func.symbol[:new_idx]
366 def valid_matching_klass(tclass):
369 elif isinstance(klass, (GLibEnum, GLibFlags)):
371 elif not isinstance(tclass, (GLibObject, GLibBoxed,
377 klass = self._uscore_type_names.get(prefix)
379 #print "NOTE: No valid matching class for likely "+\
380 # "method or constructor: %r" % (func.symbol, )
382 # Enums can't have ctors or methods
383 if isinstance(klass, (GLibEnum, GLibFlags)):
386 # The _uscore_type_names member holds the plain GLibBoxed
387 # object; we want to actually use the struct/record associated
388 if isinstance(klass, GLibBoxed):
389 name = self._transformer.remove_prefix(klass.type_name)
390 klass = self._get_attribute(name)
393 # Interfaces can't have constructors, punt to global scope
394 if isinstance(klass, GLibInterface):
395 #print "NOTE: Rejecting constructor for"+\
396 # " interface type: %r" % (func.symbol, )
398 # TODO - check that the return type is a subclass of the
399 # class from the prefix
400 # But for now, ensure that constructor returns are always
401 # the most concrete class
402 name = self._transformer.remove_prefix(klass.type_name)
403 func.retval.type = Type(name, func.retval.type.ctype)
405 self._remove_attribute(func.name)
406 # Strip namespace and object prefix: gtk_window_new -> new
407 func.name = func.symbol[len(prefix)+1:]
409 # We don't need the "this" parameter
410 del func.parameters[0]
411 klass.methods.append(func)
413 klass.constructors.append(func)
416 def _parse_struct(self, struct):
417 # This is a hack, but GObject is a rather fundamental piece so.
418 internal_names = ["Object", 'InitiallyUnowned']
419 g_internal_names = ["G" + x for x in internal_names]
420 if (self._namespace_name == 'GObject' and
421 struct.name in internal_names):
422 self._create_gobject(struct)
424 elif struct.name in g_internal_names:
427 node = self._names.names.get(struct.name)
429 self._add_attribute(struct, replace=True)
432 node.fields = struct.fields[:]
434 def _parse_union(self, union):
435 node = self._names.names.get(union.name)
437 self._add_attribute(union, replace=True)
440 node.fields = union.fields[:]
442 def _parse_callback(self, callback):
443 self._add_attribute(callback)
445 def _strip_class_suffix(self, name):
446 if (name.endswith('Class') or
447 name.endswith('Iface')):
449 elif name.endswith('Interface'):
454 def _arg_is_failed(self, param):
455 ctype = self._transformer.ctype_of(param).replace('*', '')
456 uscored = to_underscores(self._strip_class_suffix(ctype)).lower()
457 if uscored in self._failed_types:
458 print "Warning: failed type: %r" % (param, )
462 def _pair_class_struct(self, maybe_class):
463 name = self._strip_class_suffix(maybe_class.name)
464 if name == maybe_class.name:
467 if self._arg_is_failed(maybe_class):
468 print "WARNING: deleting no-type %r" % (maybe_class.name, )
469 del self._names.names[maybe_class.name]
472 # Object class fields are assumed to be read-only
473 # (see also _introspect_object and transformer.py)
474 for field in maybe_class.fields:
475 if isinstance(field, Field):
476 field.writable = False
478 name = self._resolve_type_name(name)
479 resolved = self._transformer.remove_prefix(name)
480 pair_class = self._get_attribute(resolved)
481 if pair_class and isinstance(pair_class,
482 (GLibObject, GLibInterface)):
483 for field in maybe_class.fields[1:]:
484 pair_class.fields.append(field)
486 name = self._transformer.remove_prefix(maybe_class.name)
487 pair_class = self._get_attribute(name)
488 if pair_class and isinstance(pair_class,
489 (GLibObject, GLibInterface)):
491 del self._names.names[maybe_class.name]
495 def _introspect_type(self, type_id, symbol):
496 fundamental_type_id = cgobject.type_fundamental(type_id)
497 if (fundamental_type_id == cgobject.TYPE_ENUM or
498 fundamental_type_id == cgobject.TYPE_FLAGS):
499 self._introspect_enum(fundamental_type_id, type_id, symbol)
500 elif fundamental_type_id == cgobject.TYPE_OBJECT:
501 self._introspect_object(type_id, symbol)
502 elif fundamental_type_id == cgobject.TYPE_INTERFACE:
503 self._introspect_interface(type_id, symbol)
504 elif fundamental_type_id == cgobject.TYPE_BOXED:
505 self._introspect_boxed(type_id, symbol)
506 elif fundamental_type_id == cgobject.TYPE_BOXED:
507 self._introspect_boxed(type_id, symbol)
508 elif fundamental_type_id == cgobject.TYPE_POINTER:
509 # FIXME: Should we do something about these?
510 # GHashTable, GValue and a few other fundamentals are
514 print 'unhandled GType: %s(%d)' % (cgobject.type_name(type_id),
517 def _introspect_enum(self, ftype_id, type_id, symbol):
518 type_class = cgobject.type_class_ref(type_id)
519 if type_class is None:
523 for enum_value in type_class.get_values():
524 members.append(GLibEnumMember(enum_value.value_nick,
526 enum_value.value_name,
527 enum_value.value_nick))
529 klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
530 type_name = cgobject.type_name(type_id)
531 enum_name = self._transformer.remove_prefix(type_name)
532 node = klass(enum_name, type_name, members, symbol)
533 self._add_attribute(node, replace=True)
534 self._register_internal_type(type_name, node)
536 def _introspect_object(self, type_id, symbol):
537 type_name = cgobject.type_name(type_id)
538 # We handle this specially above; in 2.16 and below there
539 # was no g_object_get_type, for later versions we need
541 if type_name == 'GObject':
543 parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
544 parent_gitype = self._resolve_gtypename(parent_type_name)
545 is_abstract = cgobject.type_is_abstract(type_id)
547 self._transformer.remove_prefix(type_name),
551 self._introspect_properties(node, type_id)
552 self._introspect_signals(node, type_id)
553 self._introspect_implemented_interfaces(node, type_id)
556 struct = self._get_attribute(node.name)
557 if struct is not None:
558 node.fields = struct.fields
559 for field in node.fields:
560 if isinstance(field, Field):
561 # Object instance fields are assumed to be read-only
562 # (see also _pair_class_struct and transformer.py)
563 field.writable = False
565 self._add_attribute(node, replace=True)
566 self._register_internal_type(type_name, node)
568 def _introspect_interface(self, type_id, symbol):
569 type_name = cgobject.type_name(type_id)
570 parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
571 if parent_type_name == 'GInterface':
574 parent_gitype = self._resolve_gtypename(parent_type_name)
575 node = GLibInterface(
576 self._transformer.remove_prefix(type_name),
579 self._introspect_properties(node, type_id)
580 self._introspect_signals(node, type_id)
581 # GtkFileChooserEmbed is an example of a private interface, we
582 # just filter them out
583 if symbol.startswith('_'):
584 print "NOTICE: Marking %s as internal type" % (type_name, )
585 self._private_internal_types[type_name] = node
587 self._add_attribute(node, replace=True)
588 self._register_internal_type(type_name, node)
590 def _introspect_boxed(self, type_id, symbol):
591 type_name = cgobject.type_name(type_id)
592 # This one doesn't go in the main namespace; we associate it with
593 # the struct or union
594 node = GLibBoxed(type_name, symbol)
595 self._boxed_types[node.type_name] = node
596 self._register_internal_type(type_name, node)
598 def _introspect_implemented_interfaces(self, node, type_id):
599 fundamental_type_id = cgobject.type_fundamental(type_id)
600 if fundamental_type_id != cgobject.TYPE_OBJECT:
602 interfaces = cgobject.type_interfaces(type_id)
604 for interface_typeid in interfaces:
605 iname = cgobject.type_name(interface_typeid)
606 gitype = self._resolve_gtypename(iname)
607 gt_interfaces.append(gitype)
608 node.interfaces = gt_interfaces
610 def _introspect_properties(self, node, type_id):
611 fundamental_type_id = cgobject.type_fundamental(type_id)
612 if fundamental_type_id == cgobject.TYPE_OBJECT:
613 pspecs = cgobject.object_class_list_properties(type_id)
614 elif fundamental_type_id == cgobject.TYPE_INTERFACE:
615 pspecs = cgobject.object_interface_list_properties(type_id)
620 if pspec.owner_type != type_id:
622 ctype = cgobject.type_name(pspec.value_type)
623 readable = (pspec.flags & 1) != 0
624 writable = (pspec.flags & 2) != 0
625 construct = (pspec.flags & 4) != 0
626 construct_only = (pspec.flags & 8) != 0
627 node.properties.append(Property(
629 type_name_from_ctype(ctype),
630 readable, writable, construct, construct_only,
634 def _introspect_signals(self, node, type_id):
635 for signal_info in cgobject.signal_list(type_id):
636 rtype = self._type_from_gtype(signal_info.return_type)
637 return_ = Return(rtype)
638 signal = GLibSignal(signal_info.signal_name, return_)
639 for i, parameter in enumerate(signal_info.get_params()):
643 name = 'p%s' % (i-1, )
644 ptype = self._type_from_gtype(parameter)
645 param = Parameter(name, ptype)
646 signal.parameters.append(param)
647 node.signals.append(signal)
651 def _resolve_type_name(self, type_name, ctype=None):
652 # Workaround glib bug #548689, to be included in 2.18.0
653 if type_name == "GParam":
654 type_name = "GObject.ParamSpec"
656 res = self._transformer.resolve_type_name_full
658 return res(type_name, ctype, self._names)
660 return self._transformer.resolve_type_name(type_name, ctype)
662 def _resolve_param_type(self, ptype, **kwargs):
663 return self._transformer.resolve_param_type_full(ptype,
667 def _resolve_node(self, node):
668 if isinstance(node, Function):
669 self._resolve_function_toplevel(node)
671 elif isinstance(node, Callback):
672 self._resolve_function(node)
673 elif isinstance(node, GLibObject):
674 self._resolve_glib_object(node)
675 elif isinstance(node, GLibInterface):
676 self._resolve_glib_interface(node)
677 elif isinstance(node, Struct):
678 self._resolve_struct(node)
679 elif isinstance(node, Union):
680 self._resolve_union(node)
681 elif isinstance(node, Alias):
682 self._resolve_alias(node)
684 def _resolve_function_toplevel(self, func):
685 newfunc = self._parse_constructor(func)
687 newfunc = self._parse_method(func)
689 self._resolve_function(func)
691 self._resolve_function(newfunc)
693 def _pair_boxed_type(self, boxed):
694 name = self._transformer.remove_prefix(boxed.type_name)
695 pair_node = self._get_attribute(name)
697 boxed_item = GLibBoxedOther(name, boxed.type_name,
699 elif isinstance(pair_node, Struct):
700 boxed_item = GLibBoxedStruct(pair_node.name, boxed.type_name,
702 boxed_item.fields = pair_node.fields
703 elif isinstance(pair_node, Union):
704 boxed_item = GLibBoxedUnion(pair_node.name, boxed.type_name,
706 boxed_item.fields = pair_node.fields
709 self._add_attribute(boxed_item, replace=True)
711 def _resolve_struct(self, node):
712 for field in node.fields:
713 self._resolve_field(field)
715 def _resolve_union(self, node):
716 for field in node.fields:
717 self._resolve_field(field)
719 def _force_resolve(self, item, allow_unknown=False):
720 if isinstance(item, Unresolved):
721 if item.target in self._private_internal_types:
724 return self._transformer.gtypename_to_giname(item.target,
728 print "WARNING: Skipping unknown interface %s" % \
733 if item in self._private_internal_types:
737 def _resolve_glib_interface(self, node):
738 node.parent = self._force_resolve(node.parent)
739 self._resolve_methods(node.methods)
740 self._resolve_properties(node.properties, node)
741 self._resolve_signals(node.signals)
743 def _resolve_glib_object(self, node):
744 node.parent = self._force_resolve(node.parent)
745 node.interfaces = filter(None,
746 [self._force_resolve(x, allow_unknown=True)
747 for x in node.interfaces])
748 self._resolve_constructors(node.constructors)
749 self._resolve_methods(node.methods)
750 self._resolve_properties(node.properties, node)
751 self._resolve_signals(node.signals)
752 for field in node.fields:
753 self._resolve_field(field)
755 def _resolve_glib_boxed(self, node):
756 self._resolve_constructors(node.constructors)
757 self._resolve_methods(node.methods)
759 def _resolve_constructors(self, constructors):
760 for ctor in constructors:
761 self._resolve_function(ctor)
763 def _resolve_methods(self, methods):
764 for method in methods:
765 self._resolve_function(method)
767 def _resolve_signals(self, signals):
768 for signal in signals:
769 self._resolve_function(signal)
771 def _resolve_properties(self, properties, context):
773 for prop in properties:
775 self._resolve_property(prop)
779 print ("WARNING: Deleting object property %r (of %r) "
780 "with unknown type") % (fail, context)
781 properties.remove(fail)
783 def _resolve_property(self, prop):
784 prop.type = self._resolve_param_type(prop.type, allow_invalid=False)
786 def _adjust_transfer(self, param):
787 # Do GLib/GObject-specific type transformations here
791 if hasattr(param.type, '_gtype'):
792 ftype = cgobject.type_fundamental(param.type._gtype)
793 assert ftype != cgobject.TYPE_INVALID, param.type._gtype
795 is_object = ftype in [cgobject.TYPE_OBJECT,
796 cgobject.TYPE_INTERFACE]
798 if ftype in [cgobject.TYPE_OBJECT,
799 cgobject.TYPE_INTERFACE,
800 cgobject.TYPE_STRING,
802 cgobject.TYPE_PARAM]:
805 # if type is a cgobject.TYPE_POINTER we could require direction
806 # and transfer-ownership annotations
809 if is_object is None:
810 is_object = (param.type.name == 'GObject.Object' or
811 (self._namespace_name == 'GObject' and
812 param.type.name == 'Object'))
814 # Default to full transfer for GObjects
815 if isinstance(param, Parameter):
816 is_out = (param.direction != PARAM_DIRECTION_IN)
819 if param.transfer is None or param.transfer_inferred:
820 if is_out and is_object:
821 param.transfer = 'full'
822 elif transfer is not None:
823 param.transfer = transfer
825 def _adjust_throws(self, func):
826 if func.parameters == []:
829 last_param = func.parameters.pop()
831 if (last_param.type.name == 'GLib.Error' or
832 (self._namespace_name == 'GLib' and
833 last_param.type.name == 'Error')):
836 func.parameters.append(last_param)
838 def _resolve_function(self, func):
839 self._resolve_parameters(func.parameters)
840 func.retval.type = self._resolve_param_type(func.retval.type)
841 self._adjust_throws(func)
842 self._adjust_transfer(func.retval)
844 def _resolve_parameters(self, parameters):
845 for parameter in parameters:
846 parameter.type = self._resolve_param_type(parameter.type)
847 self._adjust_transfer(parameter)
849 def _resolve_field(self, field):
850 if isinstance(field, Callback):
851 self._resolve_function(field)
853 field.type = self._resolve_param_type(field.type)
855 def _resolve_alias(self, alias):
856 alias.target = self._resolve_type_name(alias.target, alias.target)
860 def _validate(self, nodes):
861 nodes = list(self._names.names.itervalues())
863 self._validating = True
867 print "Type resolution; pass=%d" % (i, )
868 nodes = list(self._names.names.itervalues())
871 self._resolve_node(node)
872 except UnknownTypeError, e:
873 print "WARNING: %s: Deleting %r" % (e, node)
874 self._remove_attribute(node.name)
875 if len(nodes) == initlen:
878 self._print_statistics()
879 self._validating = False