Remove heuristic matching of methods to classes based on prefix
[gnome.gobject-introspection] / giscanner / glibtransformer.py
1 # -*- Mode: Python -*-
2 # GObject-Introspection - a framework for introspecting GObject libraries
3 # Copyright (C) 2008  Johan Dahlin
4 #
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.
9 #
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.
14 #
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
18 # 02110-1301, USA.
19 #
20
21 import os
22 import re
23 import ctypes
24 from ctypes.util import find_library
25
26 from . import cgobject
27 from .ast import (Callback, Enum, Function, Member, Namespace, Parameter,
28                   Sequence, Property, Return, Struct, Type, Alias,
29                   Union, type_name_from_ctype)
30 from .transformer import Names
31 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
32                       GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
33                       GLibBoxedUnion, GLibBoxedOther, type_names)
34 from .utils import extract_libtool, to_underscores
35
36
37 SYMBOL_BLACKLIST = [
38     # These ones break GError conventions
39     'g_simple_async_result_new_from_error',
40     'g_simple_async_result_set_from_error',
41     'g_simple_async_result_propagate_error',
42     'g_simple_async_result_report_error_in_idle',
43     'gtk_print_operation_get_error',
44 ]
45
46 SYMBOL_BLACKLIST_RE = [re.compile(x) for x in \
47                            [r'\w+_marshal_[A-Z]+__', ]]
48
49
50 class Unresolved(object):
51
52     def __init__(self, target):
53         self.target = target
54
55
56 class UnknownTypeError(Exception):
57     pass
58
59
60 class GLibTransformer(object):
61
62     def __init__(self, transformer, noclosure=False):
63         self._transformer = transformer
64         self._namespace_name = None
65         self._names = Names()
66         self._uscore_type_names = {}
67         self._libraries = []
68         self._failed_types = {}
69         self._boxed_types = {}
70         self._private_internal_types = {}
71         self._noclosure = noclosure
72         self._validating = False
73
74     # Public API
75
76     def add_library(self, libname):
77         # For testing mainly.
78         libtool_libname = 'lib' + libname + '.la'
79         if os.path.exists(libtool_libname):
80             found_libname = extract_libtool(libtool_libname)
81         elif libname.endswith('.la'):
82             found_libname = extract_libtool(libname)
83         else:
84             found_libname = find_library(libname)
85         if not found_libname:
86             raise ValueError("Failed to find library: %r" % (libname, ))
87         self._libraries.append(ctypes.cdll.LoadLibrary(found_libname))
88
89     def _print_statistics(self):
90         nodes = list(self._names.names.itervalues())
91
92         def count_type(otype):
93             return len([x for x in nodes
94                         if isinstance(x[1], otype)])
95         objectcount = count_type(GLibObject)
96         ifacecount = count_type(GLibInterface)
97         enumcount = count_type(GLibEnum)
98         print " %d nodes; %d objects, %d interfaces, %d enumsr" \
99             % (len(nodes), objectcount, ifacecount, enumcount)
100
101     def parse(self):
102         namespace = self._transformer.parse()
103         self._namespace_name = namespace.name
104
105         # First pass: parsing
106         for node in namespace.nodes:
107             self._parse_node(node)
108
109         # Introspection is done from within parsing
110
111         # Second pass: pair boxed structures
112         for boxed in self._boxed_types.itervalues():
113             self._pair_boxed_type(boxed)
114         # Third pass: delete class structures, resolve
115         # all types we now know about
116         nodes = list(self._names.names.itervalues())
117         for (ns, node) in nodes:
118             try:
119                 self._resolve_node(node)
120             except KeyError, e:
121                 print "WARNING: DELETING node %s: %s" % (node.name, e)
122                 self._remove_attribute(node.name)
123             # associate GtkButtonClass with GtkButton
124             if isinstance(node, Struct):
125                 self._pair_class_struct(node)
126         for (ns, alias) in self._names.aliases.itervalues():
127             self._resolve_alias(alias)
128
129         self._print_statistics()
130         # Fourth pass: ensure all types are known
131         if not self._noclosure:
132             self._validate(nodes)
133
134         # Create a new namespace with what we found
135         namespace = Namespace(namespace.name)
136         namespace.nodes = map(lambda x: x[1], self._names.aliases.itervalues())
137         for (ns, x) in self._names.names.itervalues():
138             namespace.nodes.append(x)
139         return namespace
140
141     # Private
142
143     def _add_attribute(self, node, replace=False):
144         node_name = node.name
145         if (not replace) and node_name in self._names.names:
146             return
147         self._names.names[node_name] = (None, node)
148
149     def _remove_attribute(self, name):
150         del self._names.names[name]
151
152     def _get_attribute(self, name):
153         node = self._names.names.get(name)
154         if node:
155             return node[1]
156         return None
157
158     def _register_internal_type(self, type_name, node):
159         self._names.type_names[type_name] = (None, node)
160         self._uscore_type_names[to_underscores(type_name).lower()] = node
161         # Besides the straight underscore conversion, we also try
162         # removing the underscores from the namespace as a possible C
163         # mapping; e.g. it's webkit_web_view, not web_kit_web_view
164         suffix = self._transformer.strip_namespace_object(type_name)
165         prefix = type_name[:-len(suffix)]
166         no_uscore_prefixed = (prefix + '_' + to_underscores(suffix)).lower()
167         self._uscore_type_names[no_uscore_prefixed] = node
168
169     # Helper functions
170
171     def _create_type(self, type_id):
172         ctype = cgobject.type_name(type_id)
173         type_name = type_name_from_ctype(ctype)
174         type_name = type_name.replace('*', '')
175         type_name = self._resolve_type_name(type_name)
176         return Type(type_name, ctype)
177
178     def _resolve_gtypename(self, gtype_name):
179         try:
180             return self._transformer.gtypename_to_giname(gtype_name,
181                                                          self._names)
182         except KeyError, e:
183             return Unresolved(gtype_name)
184
185     def _create_gobject(self, node):
186         type_name = 'G' + node.name
187         if type_name == 'GObject':
188             parent_gitype = None
189             symbol = 'intern'
190         else:
191             type_id = cgobject.type_from_name(type_name)
192             parent_type_name = cgobject.type_name(
193                 cgobject.type_parent(type_id))
194             parent_gitype = self._resolve_gtypename(parent_type_name)
195             symbol = to_underscores(type_name).lower() + '_get_type'
196         node = GLibObject(node.name, parent_gitype, type_name, symbol)
197         type_id = cgobject.TYPE_OBJECT
198         self._introspect_properties(node, type_id)
199         self._introspect_signals(node, type_id)
200         self._add_attribute(node)
201         self._register_internal_type(type_name, node)
202
203     # Parser
204
205     def _parse_node(self, node):
206         if isinstance(node, Enum):
207             self._parse_enum(node)
208         elif isinstance(node, Function):
209             self._parse_function(node)
210         elif isinstance(node, Struct):
211             self._parse_struct(node)
212         elif isinstance(node, Callback):
213             self._parse_callback(node)
214         elif isinstance(node, Alias):
215             self._parse_alias(node)
216         elif isinstance(node, Member):
217             # FIXME: atk_misc_instance singletons
218             pass
219         elif isinstance(node, Union):
220             self._parse_union(node)
221         else:
222             print 'GLIB Transformer: Unhandled node:', node
223
224     def _parse_alias(self, alias):
225         self._names.aliases[alias.name] = (None, alias)
226
227     def _parse_enum(self, enum):
228         self._add_attribute(enum)
229
230     def _parse_function(self, func):
231         if func.symbol in SYMBOL_BLACKLIST:
232             return
233         if func.symbol.startswith('_'):
234             return
235         for regexp in SYMBOL_BLACKLIST_RE:
236             if regexp.match(func.symbol):
237                 return
238         if self._parse_get_type_function(func):
239             return
240
241         self._add_attribute(func)
242
243     def _parse_get_type_function(self, func):
244         symbol = func.symbol
245         if not symbol.endswith('_get_type'):
246             return False
247         if self._namespace_name == 'GLib':
248             # No GObjects in GLib
249             return False
250         # GType *_get_type(void)
251         # This is a bit fishy, why do we need all these aliases?
252         if func.retval.type.name not in ['Type',
253                                          'GType',
254                                          'Object.Type',
255                                          'GObject.Type',
256                                          'Gtk.Type',
257                                          'GObject.GType']:
258             print ("Warning: *_get_type function returns '%r'"
259                    ", not GObject.Type") % (func.retval.type.name, )
260             return False
261         if func.parameters:
262             return False
263
264         if not self._libraries:
265             print "Warning: No libraries loaded, cannot call %s" % (symbol, )
266             return False
267
268         for library in self._libraries:
269             try:
270                 func = getattr(library, symbol)
271                 break
272             except AttributeError:
273                 continue
274         else:
275             print 'Warning: could not find symbol: %s' % symbol
276             name = symbol.replace('_get_type', '')
277             self._failed_types[name] = True
278             return False
279
280         func.restype = cgobject.GType
281         func.argtypes = []
282         type_id = func()
283         self._introspect_type(type_id, symbol)
284         return True
285
286     def _name_is_internal_gtype(self, giname):
287         try:
288             node = self._get_attribute(giname)
289             return isinstance(node, (GLibObject, GLibInterface,
290                                      GLibEnum, GLibFlags))
291         except KeyError, e:
292             return False
293
294     def _parse_method(self, func):
295         if not func.parameters:
296             return False
297         return self._parse_method_common(func, True)
298
299     def _parse_constructor(self, func):
300         return self._parse_method_common(func, False)
301
302     def _parse_method_common(self, func, is_method):
303         # Skip _get_type functions, we processed them
304         # already
305         if func.symbol.endswith('_get_type'):
306             return None
307         if self._namespace_name == 'GLib':
308             # No GObjects in GLib
309             return None
310
311         if not is_method:
312             target_arg = func.retval
313         else:
314             target_arg = func.parameters[0]
315         target_arg.type = self._resolve_param_type(target_arg.type)
316
317         if is_method:
318             # Methods require their first arg to be a known class
319             # Look at the original C type (before namespace stripping), without
320             # pointers: GtkButton -> gtk_button_, so we can figure out the
321             # method name
322             argtype = target_arg.type.ctype.replace('*', '')
323             name = self._transformer.strip_namespace_object(argtype)
324             name_uscore = to_underscores(name).lower()
325             name_offset = func.symbol.find(name_uscore)
326             if name_offset < 0:
327                 return None
328             prefix = func.symbol[:name_offset+len(name_uscore)]
329         else:
330             # Constructors must have _new
331             # Take everything before that as class name
332             new_idx = func.symbol.find('_new')
333             if new_idx < 0:
334                 return None
335             # Constructors don't return basic types
336             derefed = self._transformer.follow_aliases(target_arg.type.name,
337                                                        self._names)
338             if derefed in type_names:
339                 #print "NOTE: Rejecting constructor returning basic: %r" \
340                 #    % (func.symbol, )
341                 return None
342             prefix = func.symbol[:new_idx]
343
344         klass = None
345
346         def valid_matching_klass(tclass):
347             if tclass is None:
348                 return False
349             elif isinstance(klass, (GLibEnum, GLibFlags)):
350                 return False
351             elif not isinstance(tclass, (GLibObject, GLibBoxed,
352                                           GLibInterface)):
353                 return False
354             else:
355                 return True
356
357         klass = self._uscore_type_names.get(prefix)
358         if klass is None:
359             #print "NOTE: No valid matching class for likely "+\
360             #    "method or constructor: %r" % (func.symbol, )
361             return None
362         # Enums can't have ctors or methods
363         if isinstance(klass, (GLibEnum, GLibFlags)):
364             return None
365
366         # The _uscore_type_names member holds the plain GLibBoxed
367         # object; we want to actually use the struct/record associated
368         if isinstance(klass, GLibBoxed):
369             name = self._transformer.strip_namespace_object(klass.type_name)
370             klass = self._get_attribute(name)
371
372         if not is_method:
373             # Interfaces can't have constructors, punt to global scope
374             if isinstance(klass, (GLibInterface, GLibBoxed)):
375                 #print "NOTE: Rejecting constructor for"+\
376                 #    " interface type: %r" % (func.symbol, )
377                 return None
378             # TODO - check that the return type is a subclass of the
379             # class from the prefix
380
381         self._remove_attribute(func.name)
382         # Strip namespace and object prefix: gtk_window_new -> new
383         func.name = func.symbol[len(prefix)+1:]
384         if is_method:
385             klass.methods.append(func)
386         else:
387             klass.constructors.append(func)
388         return func
389
390     def _parse_struct(self, struct):
391         # This is a hack, but GObject is a rather fundamental piece so.
392         internal_names = ["Object", 'InitiallyUnowned']
393         g_internal_names = ["G" + x for x in internal_names]
394         if (self._namespace_name == 'GObject' and
395             struct.name in internal_names):
396             self._create_gobject(struct)
397             return
398         elif struct.name in g_internal_names:
399             # Avoid duplicates
400             return
401         node = self._names.names.get(struct.name)
402         if node is None:
403             self._add_attribute(struct, replace=True)
404             return
405         (ns, node) = node
406         node.fields = struct.fields[:]
407
408     def _parse_union(self, union):
409         node = self._names.names.get(union.name)
410         if node is None:
411             self._add_attribute(union, replace=True)
412             return
413         (ns, node) = node
414         node.fields = union.fields[:]
415
416     def _parse_callback(self, callback):
417         self._add_attribute(callback)
418
419     def _strip_class_suffix(self, name):
420         if (name.endswith('Class') or
421             name.endswith('Iface')):
422             return name[:-5]
423         elif name.endswith('Interface'):
424             return name[:-9]
425         else:
426             return name
427
428     def _arg_is_failed(self, param):
429         ctype = self._transformer.ctype_of(param).replace('*', '')
430         uscored = to_underscores(self._strip_class_suffix(ctype)).lower()
431         if uscored in self._failed_types:
432             print "Warning: failed type: %r" % (param, )
433             return True
434         return False
435
436     def _pair_class_struct(self, maybe_class):
437         name = self._strip_class_suffix(maybe_class.name)
438         if name == maybe_class.name:
439             return
440
441         if self._arg_is_failed(maybe_class):
442             print "WARNING: deleting no-type %r" % (maybe_class.name, )
443             del self._names.names[maybe_class.name]
444             return
445
446         name = self._resolve_type_name(name)
447         resolved = self._transformer.strip_namespace_object(name)
448         pair_class = self._get_attribute(resolved)
449         if pair_class and isinstance(pair_class,
450                                      (GLibObject, GLibInterface)):
451             for field in maybe_class.fields[1:]:
452                 pair_class.fields.append(field)
453             return
454         name = self._transformer.strip_namespace_object(maybe_class.name)
455         pair_class = self._get_attribute(name)
456         if pair_class and isinstance(pair_class,
457                                      (GLibObject, GLibInterface)):
458
459             del self._names.names[maybe_class.name]
460
461     # Introspection
462
463     def _introspect_type(self, type_id, symbol):
464         fundamental_type_id = cgobject.type_fundamental(type_id)
465         if (fundamental_type_id == cgobject.TYPE_ENUM or
466             fundamental_type_id == cgobject.TYPE_FLAGS):
467             self._introspect_enum(fundamental_type_id, type_id, symbol)
468         elif fundamental_type_id == cgobject.TYPE_OBJECT:
469             self._introspect_object(type_id, symbol)
470         elif fundamental_type_id == cgobject.TYPE_INTERFACE:
471             self._introspect_interface(type_id, symbol)
472         elif fundamental_type_id == cgobject.TYPE_BOXED:
473             self._introspect_boxed(type_id, symbol)
474         elif fundamental_type_id == cgobject.TYPE_BOXED:
475             self._introspect_boxed(type_id, symbol)
476         elif fundamental_type_id == cgobject.TYPE_POINTER:
477             # FIXME: Should we do something about these?
478             #        GHashTable, GValue and a few other fundamentals are
479             #        covered here
480             return
481         else:
482             print 'unhandled GType: %s(%d)' % (cgobject.type_name(type_id),
483                                                type_id)
484
485     def _introspect_enum(self, ftype_id, type_id, symbol):
486         type_class = cgobject.type_class_ref(type_id)
487         if type_class is None:
488             return
489
490         members = []
491         for enum_value in type_class.get_values():
492             members.append(GLibEnumMember(enum_value.value_nick,
493                                           enum_value.value,
494                                           enum_value.value_name,
495                                           enum_value.value_nick))
496
497         klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
498         type_name = cgobject.type_name(type_id)
499         enum_name = self._transformer.strip_namespace_object(type_name)
500         node = klass(enum_name, type_name, members, symbol)
501         self._add_attribute(node, replace=True)
502         self._register_internal_type(type_name, node)
503
504     def _introspect_object(self, type_id, symbol):
505         type_name = cgobject.type_name(type_id)
506         # We handle this specially above; in 2.16 and below there
507         # was no g_object_get_type, for later versions we need
508         # to skip it
509         if type_name == 'GObject':
510             return
511         parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
512         parent_gitype = self._resolve_gtypename(parent_type_name)
513         node = GLibObject(
514             self._transformer.strip_namespace_object(type_name),
515             parent_gitype,
516             type_name, symbol)
517         self._introspect_properties(node, type_id)
518         self._introspect_signals(node, type_id)
519         self._introspect_implemented_interfaces(node, type_id)
520         self._add_attribute(node, replace=True)
521         self._register_internal_type(type_name, node)
522
523     def _introspect_interface(self, type_id, symbol):
524         type_name = cgobject.type_name(type_id)
525         parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
526         if parent_type_name == 'GInterface':
527             parent_gitype = None
528         else:
529             parent_gitype = self._resolve_gtypename(parent_type_name)
530         node = GLibInterface(
531             self._transformer.strip_namespace_object(type_name),
532             parent_gitype,
533             type_name, symbol)
534         self._introspect_properties(node, type_id)
535         self._introspect_signals(node, type_id)
536         # GtkFileChooserEmbed is an example of a private interface, we
537         # just filter them out
538         if symbol.startswith('_'):
539             print "NOTICE: Marking %s as internal type" % (type_name, )
540             self._private_internal_types[type_name] = node
541         else:
542             self._add_attribute(node, replace=True)
543             self._register_internal_type(type_name, node)
544
545     def _introspect_boxed(self, type_id, symbol):
546         type_name = cgobject.type_name(type_id)
547         # This one doesn't go in the main namespace; we associate it with
548         # the struct or union
549         node = GLibBoxed(type_name, symbol)
550         self._boxed_types[node.type_name] = node
551         self._register_internal_type(type_name, node)
552
553     def _introspect_implemented_interfaces(self, node, type_id):
554         fundamental_type_id = cgobject.type_fundamental(type_id)
555         if fundamental_type_id != cgobject.TYPE_OBJECT:
556             raise AssertionError
557         interfaces = cgobject.type_interfaces(type_id)
558         gt_interfaces = []
559         for interface_typeid in interfaces:
560             iname = cgobject.type_name(interface_typeid)
561             gitype = self._resolve_gtypename(iname)
562             gt_interfaces.append(gitype)
563         node.interfaces = gt_interfaces
564
565     def _introspect_properties(self, node, type_id):
566         fundamental_type_id = cgobject.type_fundamental(type_id)
567         if fundamental_type_id == cgobject.TYPE_OBJECT:
568             pspecs = cgobject.object_class_list_properties(type_id)
569         elif fundamental_type_id == cgobject.TYPE_INTERFACE:
570             pspecs = cgobject.object_interface_list_properties(type_id)
571         else:
572             raise AssertionError
573
574         for pspec in pspecs:
575             if pspec.owner_type != type_id:
576                 continue
577             ctype = cgobject.type_name(pspec.value_type)
578             readable = (pspec.flags & 1) != 0
579             writable = (pspec.flags & 2) != 0
580             construct = (pspec.flags & 4) != 0
581             construct_only = (pspec.flags & 8) != 0
582             node.properties.append(Property(
583                 pspec.name,
584                 type_name_from_ctype(ctype),
585                 readable, writable, construct, construct_only,
586                 ctype,
587                 ))
588
589     def _introspect_signals(self, node, type_id):
590         for signal_info in cgobject.signal_list(type_id):
591             rtype = self._create_type(signal_info.return_type)
592             return_ = Return(rtype)
593             signal = GLibSignal(signal_info.signal_name, return_)
594             for i, parameter in enumerate(signal_info.get_params()):
595                 if i == 0:
596                     name = 'object'
597                 else:
598                     name = 'p%s' % (i-1, )
599                 ptype = self._create_type(parameter)
600                 param = Parameter(name, ptype)
601                 signal.parameters.append(param)
602             node.signals.append(signal)
603
604     # Resolver
605
606     def _resolve_type_name(self, type_name, ctype=None):
607         # Workaround glib bug #548689, to be included in 2.18.0
608         if type_name == "GParam":
609             type_name = "GObject.ParamSpec"
610
611         res = self._transformer.resolve_type_name_full
612         try:
613             return res(type_name, ctype, self._names)
614         except KeyError, e:
615             return self._transformer.resolve_type_name(type_name, ctype)
616
617     def _validate_type_name(self, name):
618         if name in type_names:
619             return True
620         if name.find('.') >= 0:
621             return True
622         if name in self._names.aliases:
623             return True
624         if name in self._names.names:
625             return True
626         return False
627
628     def _validate_type(self, ptype):
629         if isinstance(ptype, Sequence):
630             etype = ptype.element_type
631             if isinstance(etype, Sequence):
632                 return self._validate_type(etype)
633             return self._validate_type_name(etype)
634         return self._validate_type_name(ptype.name)
635
636     def _resolve_param_type_validate(self, ptype):
637         ptype = self._resolve_param_type(ptype)
638         if self._validating and not self._validate_type(ptype):
639             raise UnknownTypeError("Unknown type %r" % (ptype, ))
640         return ptype
641
642     def _resolve_param_type(self, ptype):
643         try:
644             return self._transformer.resolve_param_type_full(ptype,
645                                                              self._names)
646         except KeyError, e:
647             return self._transformer.resolve_param_type(ptype)
648         return ptype
649
650     def _resolve_node(self, node):
651         if isinstance(node, Function):
652             self._resolve_function_toplevel(node)
653
654         elif isinstance(node, Callback):
655             self._resolve_function(node)
656         elif isinstance(node, GLibObject):
657             self._resolve_glib_object(node)
658         elif isinstance(node, GLibInterface):
659             self._resolve_glib_interface(node)
660         elif isinstance(node, Struct):
661             self._resolve_struct(node)
662         elif isinstance(node, Union):
663             self._resolve_union(node)
664         elif isinstance(node, Alias):
665             self._resolve_alias(node)
666
667     def _resolve_function_toplevel(self, func):
668         newfunc = self._parse_constructor(func)
669         if not newfunc:
670             newfunc = self._parse_method(func)
671             if not newfunc:
672                 self._resolve_function(func)
673                 return
674         self._resolve_function(newfunc)
675
676     def _pair_boxed_type(self, boxed):
677         name = self._transformer.strip_namespace_object(boxed.type_name)
678         pair_node = self._get_attribute(name)
679         if not pair_node:
680             boxed_item = GLibBoxedOther(name, boxed.type_name,
681                                         boxed.get_type)
682         elif isinstance(pair_node, Struct):
683             boxed_item = GLibBoxedStruct(pair_node.name, boxed.type_name,
684                                          boxed.get_type)
685             boxed_item.fields = pair_node.fields
686         elif isinstance(pair_node, Union):
687             boxed_item = GLibBoxedUnion(pair_node.name, boxed.type_name,
688                                          boxed.get_type)
689             boxed_item.fields = pair_node.fields
690         else:
691             return False
692         self._add_attribute(boxed_item, replace=True)
693
694     def _resolve_struct(self, node):
695         for field in node.fields:
696             self._resolve_field(field)
697
698     def _resolve_union(self, node):
699         for field in node.fields:
700             self._resolve_field(field)
701
702     def _force_resolve(self, item, allow_unknown=False):
703         if isinstance(item, Unresolved):
704             if item.target in self._private_internal_types:
705                 return None
706             try:
707                 return self._transformer.gtypename_to_giname(item.target,
708                                                              self._names)
709             except KeyError, e:
710                 if allow_unknown:
711                     print "WARNING: Skipping unknown interface %s" % \
712                         (item.target, )
713                     return None
714                 else:
715                     raise
716         if item in self._private_internal_types:
717             return None
718         return item
719
720     def _resolve_glib_interface(self, node):
721         node.parent = self._force_resolve(node.parent)
722         self._resolve_methods(node.methods)
723         self._resolve_properties(node.properties)
724         self._resolve_signals(node.signals)
725
726     def _resolve_glib_object(self, node):
727         node.parent = self._force_resolve(node.parent)
728         node.interfaces = filter(None,
729             [self._force_resolve(x, allow_unknown=True)
730                                     for x in node.interfaces])
731         self._resolve_constructors(node.constructors)
732         self._resolve_methods(node.methods)
733         self._resolve_properties(node.properties)
734         self._resolve_signals(node.signals)
735
736     def _resolve_glib_boxed(self, node):
737         self._resolve_constructors(node.constructors)
738         self._resolve_methods(node.methods)
739
740     def _resolve_constructors(self, constructors):
741         for ctor in constructors:
742             self._resolve_function(ctor)
743
744     def _resolve_methods(self, methods):
745         for method in methods:
746             self._resolve_function(method)
747
748     def _resolve_signals(self, signals):
749         for signal in signals:
750             self._resolve_function(signal)
751
752     def _resolve_properties(self, properties):
753         for prop in properties:
754             self._resolve_property(prop)
755
756     def _resolve_property(self, prop):
757         prop.type = self._resolve_param_type(prop.type)
758
759     def _resolve_function(self, func):
760         self._resolve_parameters(func.parameters)
761         func.retval.type = self._resolve_param_type(func.retval.type)
762
763     def _resolve_parameters(self, parameters):
764         for parameter in parameters:
765             parameter.type = self._resolve_param_type(parameter.type)
766
767     def _resolve_field(self, field):
768         if isinstance(field, Callback):
769             self._resolve_function(field)
770             return
771         field.type = self._resolve_param_type(field.type)
772
773     def _resolve_alias(self, alias):
774         alias.target = self._resolve_type_name(alias.target, alias.target)
775
776     # Validation
777
778     def _validate(self, nodes):
779         nodes = list(self._names.names.itervalues())
780         i = 0
781         self._validating = True
782         while True:
783             initlen = len(nodes)
784
785             print "Type resolution; pass=%d" % (i, )
786             nodes = list(self._names.names.itervalues())
787             for node in nodes:
788                 try:
789                     self._resolve_node(node)
790                 except UnknownTypeError, e:
791                     print "WARNING: %s: Deleting %r" % (e, node)
792                     self._remove_attribute(node.name)
793             if len(nodes) == initlen:
794                 break
795             i += 1
796             self._print_statistics()
797         self._validating = False