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.
28 from .ast import (Alias, Bitfield, Callback, Constant, Enum, Function, Member,
29 Namespace, Parameter, Property, Record, Return, Type, Union,
30 Field, type_name_from_ctype,
31 default_array_types, TYPE_UINT8, PARAM_TRANSFER_FULL)
32 from .transformer import Names
33 from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
34 GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
35 GLibBoxedUnion, GLibBoxedOther, GLibRecord, type_names)
36 from .utils import to_underscores, to_underscores_noprefix
38 default_array_types['guchar*'] = TYPE_UINT8
41 G_PARAM_READABLE = 1 << 0
42 G_PARAM_WRITABLE = 1 << 1
43 G_PARAM_CONSTRUCT = 1 << 2
44 G_PARAM_CONSTRUCT_ONLY = 1 << 3
45 G_PARAM_LAX_VALIDATION = 1 << 4
46 G_PARAM_STATIC_NAME = 1 << 5
47 G_PARAM_STATIC_NICK = 1 << 6
48 G_PARAM_STATIC_BLURB = 1 << 7
51 # These ones break GError conventions
52 'g_simple_async_result_new_from_error',
53 'g_simple_async_result_set_from_error',
54 'g_simple_async_result_propagate_error',
55 'g_simple_async_result_report_error_in_idle',
56 'gtk_print_operation_get_error',
59 SYMBOL_BLACKLIST_RE = [re.compile(x) for x in \
60 [r'\w+_marshal_[A-Z]+__', ]]
63 class IntrospectionBinary(object):
65 def __init__(self, args, tmpdir=None):
68 self.tmpdir = tempfile.mkdtemp('', 'tmp-introspect')
73 class Unresolved(object):
75 def __init__(self, target):
79 class UnknownTypeError(Exception):
83 class GLibTransformer(object):
85 def __init__(self, transformer, noclosure=False):
86 self._transformer = transformer
87 self._noclosure = noclosure
88 self._namespace_name = None
90 self._uscore_type_names = {}
92 self._get_type_functions = []
93 self._error_quark_functions = []
95 self._failed_types = {}
96 self._boxed_types = {}
97 self._private_internal_types = {}
98 self._validating = False
102 def _print_statistics(self):
103 nodes = list(self._names.names.itervalues())
105 def count_type(otype):
106 return len([x for x in nodes
107 if isinstance(x[1], otype)])
108 objectcount = count_type(GLibObject)
109 ifacecount = count_type(GLibInterface)
110 enumcount = count_type(GLibEnum)
111 print " %d nodes; %d objects, %d interfaces, %d enums" \
112 % (len(nodes), objectcount, ifacecount, enumcount)
114 def init_parse(self):
115 """Do parsing steps that don't involve the introspection binary
117 This does enough work that get_type_functions() can be called.
121 namespace = self._transformer.parse()
122 self._namespace_name = namespace.name
123 self._namespace_version = namespace.version
125 # First pass: parsing
126 for node in namespace.nodes:
127 self._parse_node(node)
129 # We don't want an alias for this - it's handled specially in
130 # the typelib compiler.
131 if namespace.name == 'GObject':
132 del self._names.aliases['Type']
134 def get_get_type_functions(self):
135 return self._get_type_functions
137 def set_introspection_binary(self, binary):
138 self._binary = binary
141 """Do remaining parsing steps requiring introspection binary"""
143 # Get all the GObject data by passing our list of get_type
144 # functions to the compiled binary
146 self._execute_binary()
148 # Introspection is done from within parsing
150 # Second pass: pair boxed structures
151 for boxed in self._boxed_types.itervalues():
152 self._pair_boxed_type(boxed)
153 # Third pass: delete class structures, resolve
154 # all types we now know about
155 nodes = list(self._names.names.itervalues())
156 for (ns, node) in nodes:
158 self._resolve_node(node)
160 print "WARNING: DELETING node %s: %s" % (node.name, e)
161 self._remove_attribute(node.name)
162 # Another pass, since we need to have the methods parsed
163 # in order to correctly modify them after class/record
165 for (ns, node) in nodes:
166 # associate GtkButtonClass with GtkButton
167 if isinstance(node, Record):
168 self._pair_class_record(node)
169 for (ns, alias) in self._names.aliases.itervalues():
170 self._resolve_alias(alias)
171 self._resolve_quarks()
172 # Fourth pass: ensure all types are known
173 if not self._noclosure:
174 self._validate(nodes)
176 # Create a new namespace with what we found
177 namespace = Namespace(self._namespace_name, self._namespace_version)
178 namespace.nodes = map(lambda x: x[1], self._names.aliases.itervalues())
179 for (ns, x) in self._names.names.itervalues():
180 namespace.nodes.append(x)
185 def _add_attribute(self, node, replace=False):
186 node_name = node.name
187 if (not replace) and node_name in self._names.names:
189 self._names.names[node_name] = (None, node)
191 def _remove_attribute(self, name):
192 del self._names.names[name]
194 def _get_attribute(self, name):
195 node = self._names.names.get(name)
200 def _lookup_node(self, name):
201 if name in type_names:
203 node = self._get_attribute(name)
205 node = self._transformer.get_names().names.get(name)
210 def _register_internal_type(self, type_name, node):
211 self._names.type_names[type_name] = (None, node)
212 uscored = to_underscores(type_name).lower()
213 self._uscore_type_names[uscored] = node
214 # Besides the straight underscore conversion, we also try
215 # removing the underscores from the namespace as a possible C
216 # mapping; e.g. it's webkit_web_view, not web_kit_web_view
217 suffix = self._transformer.remove_prefix(type_name)
218 prefix = type_name[:-len(suffix)]
219 no_uscore_prefixed = (prefix + '_' + to_underscores(suffix)).lower()
220 self._uscore_type_names[no_uscore_prefixed] = node
222 def _resolve_quarks(self):
223 for node in self._error_quark_functions:
224 short = node.symbol[:-len('_quark')]
225 enum = self._uscore_type_names.get(short)
227 enum.error_quark = node.symbol
231 def _resolve_gtypename(self, gtype_name):
233 return self._transformer.gtypename_to_giname(gtype_name,
236 return Unresolved(gtype_name)
238 def _execute_binary(self):
239 in_path = os.path.join(self._binary.tmpdir, 'types.txt')
240 f = open(in_path, 'w')
241 # TODO: Introspect GQuark functions
242 for func in self._get_type_functions:
246 out_path = os.path.join(self._binary.tmpdir, 'dump.xml')
249 args.extend(self._binary.args)
250 args.append('--introspect-dump=%s,%s' % (in_path, out_path))
252 # Invoke the binary, having written our get_type functions to types.txt
254 subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
255 except subprocess.CalledProcessError, e:
257 self._read_introspect_dump(out_path)
259 # Clean up temporaries
260 shutil.rmtree(self._binary.tmpdir)
262 def _read_introspect_dump(self, xmlpath):
263 from xml.etree.cElementTree import parse
264 tree = parse(xmlpath)
265 root = tree.getroot()
267 self._gtype_data[child.attrib['name']] = child
269 self._introspect_type(child)
271 def _create_gobject(self, node):
272 type_name = 'G' + node.name
273 if type_name == 'GObject':
276 elif type_name == 'GInitiallyUnowned':
277 parent_type_name = 'GObject'
278 parent_gitype = self._resolve_gtypename(parent_type_name)
279 symbol = 'g_initially_unowned_get_type'
282 gnode = GLibObject(node.name, parent_gitype, type_name, symbol, True)
283 if type_name == 'GObject':
284 gnode.fields.extend(node.fields)
286 # http://bugzilla.gnome.org/show_bug.cgi?id=569408
287 # GInitiallyUnowned is actually a typedef for GObject, but
288 # that's not reflected in the GIR, where it appears as a
289 # subclass (as it appears in the GType hierarchy). So
290 # what we do here is copy all of the GObject fields into
291 # GInitiallyUnowned so that struct offset computation
293 gnode.fields = self._names.names['Object'][1].fields
294 self._add_attribute(gnode)
295 self._register_internal_type(type_name, gnode)
299 def _parse_node(self, node):
300 if isinstance(node, Enum):
301 self._parse_enum(node)
302 elif isinstance(node, Bitfield):
303 self._parse_bitfield(node)
304 elif isinstance(node, Function):
305 self._parse_function(node)
306 elif isinstance(node, Record):
307 self._parse_record(node)
308 elif isinstance(node, Callback):
309 self._parse_callback(node)
310 elif isinstance(node, Alias):
311 self._parse_alias(node)
312 elif isinstance(node, Member):
313 # FIXME: atk_misc_instance singletons
315 elif isinstance(node, Union):
316 self._parse_union(node)
317 elif isinstance(node, Constant):
318 self._parse_constant(node)
320 print 'GLIB Transformer: Unhandled node:', node
322 def _parse_alias(self, alias):
323 self._names.aliases[alias.name] = (None, alias)
325 def _parse_enum(self, enum):
326 self._add_attribute(enum)
328 def _parse_bitfield(self, enum):
329 self._add_attribute(enum)
331 def _parse_constant(self, constant):
332 self._add_attribute(constant)
334 def _parse_function(self, func):
335 if func.symbol in SYMBOL_BLACKLIST:
337 if func.symbol.startswith('_'):
339 for regexp in SYMBOL_BLACKLIST_RE:
340 if regexp.match(func.symbol):
342 if self._parse_get_type_function(func):
344 if self._parse_error_quark_function(func):
347 self._add_attribute(func)
349 def _parse_get_type_function(self, func):
351 if not symbol.endswith('_get_type'):
353 if self._namespace_name == 'GLib':
354 # No GObjects in GLib
356 if (self._namespace_name == 'GObject' and
357 symbol in ('g_object_get_type', 'g_initially_unowned_get_type')):
358 # We handle these internally, see _create_gobject
362 # GType *_get_type(void)
363 if func.retval.type.name not in ['Type',
367 print ("Warning: *_get_type function returns '%r'"
368 ", not GObject.Type") % (func.retval.type.name, )
371 self._get_type_functions.append(symbol)
374 def _parse_error_quark_function(self, func):
375 if not func.symbol.endswith('_error_quark'):
379 if func.retval.type.name not in ['GLib.Quark',
383 self._error_quark_functions.append(func)
386 def _name_is_internal_gtype(self, giname):
388 node = self._get_attribute(giname)
389 return isinstance(node, (GLibObject, GLibInterface,
390 GLibBoxed, GLibEnum, GLibFlags))
394 def _parse_static_method(self, func):
395 components = func.symbol.split('_')
396 if len(components) < 2:
399 prefix_components = None
401 for i in xrange(1, len(components)-1):
402 prefix_components = '_'.join(components[0:-i])
403 methname = '_'.join(components[-i:])
404 target_klass = self._uscore_type_names.get(prefix_components)
405 if target_klass and isinstance(target_klass, GLibObject):
410 self._remove_attribute(func.name)
412 target_klass.static_methods.append(func)
413 func.is_method = True
416 def _parse_method(self, func):
417 if not func.parameters:
419 return self._parse_method_common(func, True)
421 def _parse_constructor(self, func):
422 return self._parse_method_common(func, False)
424 def _parse_method_common(self, func, is_method):
425 # Skip _get_type functions, we processed them
427 if func.symbol.endswith('_get_type'):
429 if self._namespace_name == 'GLib':
430 # No GObjects in GLib
434 target_arg = func.retval
436 target_arg = func.parameters[0]
439 # Methods require their first arg to be a known class
440 # Look at the original C type (before namespace stripping), without
441 # pointers: GtkButton -> gtk_button_, so we can figure out the
443 argtype = target_arg.type.ctype.replace('*', '')
444 name = self._transformer.remove_prefix(argtype)
445 name_uscore = to_underscores_noprefix(name).lower()
446 name_offset = func.symbol.find(name_uscore)
449 prefix = func.symbol[:name_offset+len(name_uscore)]
451 # Constructors must have _new
452 # Take everything before that as class name
453 new_idx = func.symbol.find('_new')
456 # Constructors don't return basic types
457 derefed = self._transformer.follow_aliases(target_arg.type.name,
459 if derefed in type_names:
460 #print "NOTE: Rejecting constructor returning basic: %r" \
463 prefix = func.symbol[:new_idx]
465 klass = self._uscore_type_names.get(prefix)
467 #print "NOTE: No valid matching class for likely "+\
468 # "method or constructor: %r" % (func.symbol, )
470 # Enums can't have ctors or methods
471 if isinstance(klass, (GLibEnum, GLibFlags)):
474 # The _uscore_type_names member holds the plain GLibBoxed
475 # object; we want to actually use the struct/record associated
476 if isinstance(klass, (Record, Union)):
477 remove_prefix = klass.symbol
479 remove_prefix = klass.type_name
481 name = self._transformer.remove_prefix(remove_prefix)
482 klass = self._get_attribute(name)
487 # Interfaces can't have constructors, punt to global scope
488 if isinstance(klass, GLibInterface):
489 #print "NOTE: Rejecting constructor for"+\
490 # " interface type: %r" % (func.symbol, )
492 # TODO - check that the return type is a subclass of the
493 # class from the prefix
494 # But for now, ensure that constructor returns are always
495 # the most concrete class
496 name = self._transformer.remove_prefix(remove_prefix)
497 func.retval.type = Type(name, func.retval.type.ctype)
499 self._remove_attribute(func.name)
500 # Strip namespace and object prefix: gtk_window_new -> new
501 func.name = func.symbol[len(prefix)+1:]
503 # We don't need the "this" parameter
504 del func.parameters[0]
505 klass.methods.append(func)
506 func.is_method = True
508 klass.constructors.append(func)
511 def _parse_record(self, record):
512 # This is a hack, but GObject is a rather fundamental piece so.
513 internal_names = ["Object", 'InitiallyUnowned']
514 g_internal_names = ["G" + x for x in internal_names]
515 if (self._namespace_name == 'GObject' and
516 record.name in internal_names):
517 self._create_gobject(record)
519 elif record.name in g_internal_names:
522 node = self._names.names.get(record.name)
524 self._add_attribute(record, replace=True)
525 self._register_internal_type(record.symbol, record)
528 node.fields = record.fields[:]
530 def _parse_union(self, union):
531 node = self._names.names.get(union.name)
533 self._add_attribute(union, replace=True)
534 self._register_internal_type(union.symbol, union)
537 node.fields = union.fields[:]
539 def _parse_callback(self, callback):
540 self._add_attribute(callback)
542 def _strip_class_suffix(self, name):
543 if (name.endswith('Class') or
544 name.endswith('Iface')):
546 elif name.endswith('Interface'):
551 def _arg_is_failed(self, param):
552 ctype = self._transformer.ctype_of(param).replace('*', '')
553 uscored = to_underscores(self._strip_class_suffix(ctype)).lower()
554 if uscored in self._failed_types:
555 print "Warning: failed type: %r" % (param, )
559 def _pair_class_record(self, maybe_class):
560 name = self._strip_class_suffix(maybe_class.name)
561 if name == maybe_class.name:
564 class_struct = maybe_class
565 if self._arg_is_failed(class_struct):
566 print "WARNING: deleting no-type %r" % (class_struct.name, )
567 del self._names.names[class_struct.name]
570 pair_class = self._get_attribute(name)
571 if (not pair_class or
572 not isinstance(pair_class, (GLibObject, GLibInterface))):
575 # Object class fields are assumed to be read-only
576 # (see also _introspect_object and transformer.py)
577 for field in maybe_class.fields:
578 if isinstance(field, Field):
579 field.writable = False
581 # Pair up virtual methods by finding a slot in
582 # the class with the same name
583 for field in maybe_class.fields:
584 if not isinstance(field, Callback):
587 for method in pair_class.methods:
588 if (method.name == field.name and
589 len(method.parameters)+1 == len(field.parameters)):
590 method.is_virtual = True
593 gclass_struct = GLibRecord.from_record(class_struct)
594 self._remove_attribute(class_struct.name)
595 self._add_attribute(gclass_struct, True)
596 pair_class.glib_type_struct = gclass_struct
597 gclass_struct.is_gtype_struct_for = name
601 def _introspect_type(self, xmlnode):
602 if xmlnode.tag in ('enum', 'flags'):
603 self._introspect_enum(xmlnode)
604 elif xmlnode.tag == 'class':
605 self._introspect_object(xmlnode)
606 elif xmlnode.tag == 'interface':
607 self._introspect_interface(xmlnode)
608 elif xmlnode.tag == 'boxed':
609 self._introspect_boxed(xmlnode)
611 raise ValueError("Unhandled introspection XML tag %s", xmlnode.tag)
613 def _introspect_enum(self, node):
615 for member in node.findall('member'):
616 members.append(GLibEnumMember(member.attrib['nick'],
617 member.attrib['value'],
618 member.attrib['name'],
619 member.attrib['nick']))
621 klass = (GLibFlags if node.tag == 'flags' else GLibEnum)
622 type_name = node.attrib['name']
623 enum_name = self._transformer.remove_prefix(type_name)
624 node = klass(enum_name, type_name, members, node.attrib['get-type'])
625 self._add_attribute(node, replace=True)
626 self._register_internal_type(type_name, node)
628 def _introspect_object(self, xmlnode):
629 type_name = xmlnode.attrib['name']
630 # We handle this specially above; in 2.16 and below there
631 # was no g_object_get_type, for later versions we need
633 if type_name == 'GObject':
635 parent_type_name = xmlnode.attrib['parent']
636 parent_gitype = self._resolve_gtypename(parent_type_name)
637 is_abstract = not not xmlnode.attrib.get('abstract', False)
639 self._transformer.remove_prefix(type_name),
642 xmlnode.attrib['get-type'], is_abstract)
643 self._introspect_properties(node, xmlnode)
644 self._introspect_signals(node, xmlnode)
645 self._introspect_implemented_interfaces(node, xmlnode)
648 record = self._get_attribute(node.name)
649 if record is not None:
650 node.fields = record.fields
651 for field in node.fields:
652 if isinstance(field, Field):
653 # Object instance fields are assumed to be read-only
654 # (see also _pair_class_record and transformer.py)
655 field.writable = False
657 self._add_attribute(node, replace=True)
658 self._register_internal_type(type_name, node)
660 def _introspect_interface(self, xmlnode):
661 type_name = xmlnode.attrib['name']
662 node = GLibInterface(
663 self._transformer.remove_prefix(type_name),
665 type_name, xmlnode.attrib['get-type'])
666 self._introspect_properties(node, xmlnode)
667 self._introspect_signals(node, xmlnode)
668 for child in xmlnode.findall('prerequisite'):
669 name = child.attrib['name']
670 prereq = self._resolve_gtypename(name)
671 node.prerequisites.append(prereq)
672 # GtkFileChooserEmbed is an example of a private interface, we
673 # just filter them out
674 if xmlnode.attrib['get-type'].startswith('_'):
675 print "NOTICE: Marking %s as internal type" % (type_name, )
676 self._private_internal_types[type_name] = node
678 self._add_attribute(node, replace=True)
679 self._register_internal_type(type_name, node)
681 def _introspect_boxed(self, xmlnode):
682 type_name = xmlnode.attrib['name']
683 # This one doesn't go in the main namespace; we associate it with
684 # the struct or union
685 node = GLibBoxed(type_name, xmlnode.attrib['get-type'])
686 self._boxed_types[node.type_name] = node
687 self._register_internal_type(type_name, node)
689 def _introspect_implemented_interfaces(self, node, xmlnode):
691 for interface in xmlnode.findall('implements'):
692 gitype = self._resolve_gtypename(interface.attrib['name'])
693 gt_interfaces.append(gitype)
694 node.interfaces = gt_interfaces
696 def _introspect_properties(self, node, xmlnode):
697 for pspec in xmlnode.findall('property'):
698 ctype = pspec.attrib['type']
699 flags = int(pspec.attrib['flags'])
700 readable = (flags & G_PARAM_READABLE) != 0
701 writable = (flags & G_PARAM_WRITABLE) != 0
702 construct = (flags & G_PARAM_CONSTRUCT) != 0
703 construct_only = (flags & G_PARAM_CONSTRUCT_ONLY) != 0
704 node.properties.append(Property(
705 pspec.attrib['name'],
706 type_name_from_ctype(ctype),
707 readable, writable, construct, construct_only,
711 def _introspect_signals(self, node, xmlnode):
712 for signal_info in xmlnode.findall('signal'):
713 rctype = signal_info.attrib['return']
714 rtype = Type(self._transformer.parse_ctype(rctype), rctype)
715 return_ = Return(rtype, signal_info.attrib['return'])
716 return_.transfer = PARAM_TRANSFER_FULL
717 signal = GLibSignal(signal_info.attrib['name'], return_)
718 for i, parameter in enumerate(signal_info.findall('param')):
722 name = 'p%s' % (i-1, )
723 pctype = parameter.attrib['type']
724 ptype = Type(self._transformer.parse_ctype(pctype), pctype)
725 param = Parameter(name, ptype)
726 param.transfer = 'none'
727 signal.parameters.append(param)
728 node.signals.append(signal)
732 def _resolve_type_name(self, type_name, ctype=None):
733 # Workaround glib bug #548689, to be included in 2.18.0
734 if type_name == "GParam":
735 type_name = "GObject.ParamSpec"
736 res = self._transformer.resolve_type_name_full
738 return res(type_name, ctype, self._names)
740 return self._transformer.resolve_type_name(type_name, ctype)
742 def _resolve_param_type(self, ptype, **kwargs):
743 # Workaround glib bug #548689, to be included in 2.18.0
744 if ptype.name == "GParam":
745 ptype.name = "GObject.ParamSpec"
746 return self._transformer.resolve_param_type_full(ptype,
750 def _resolve_node(self, node):
751 if isinstance(node, Function):
752 self._resolve_function_toplevel(node)
754 elif isinstance(node, Callback):
755 self._resolve_function(node)
756 elif isinstance(node, GLibObject):
757 self._resolve_glib_object(node)
758 elif isinstance(node, GLibInterface):
759 self._resolve_glib_interface(node)
760 elif isinstance(node, Record):
761 self._resolve_record(node)
762 elif isinstance(node, Union):
763 self._resolve_union(node)
764 elif isinstance(node, Alias):
765 self._resolve_alias(node)
767 def _resolve_function_toplevel(self, func):
768 for parser in [self._parse_constructor,
770 self._parse_static_method]:
771 newfunc = parser(func)
773 self._resolve_function(newfunc)
775 self._resolve_function(func)
777 def _pair_boxed_type(self, boxed):
778 name = self._transformer.remove_prefix(boxed.type_name)
779 pair_node = self._get_attribute(name)
781 boxed_item = GLibBoxedOther(name, boxed.type_name,
783 elif isinstance(pair_node, Record):
784 boxed_item = GLibBoxedStruct(pair_node.name, boxed.type_name,
786 boxed_item.fields = pair_node.fields
787 elif isinstance(pair_node, Union):
788 boxed_item = GLibBoxedUnion(pair_node.name, boxed.type_name,
790 boxed_item.fields = pair_node.fields
793 self._add_attribute(boxed_item, replace=True)
795 def _resolve_record(self, node):
796 for field in node.fields:
797 self._resolve_field(field)
799 def _resolve_union(self, node):
800 for field in node.fields:
801 self._resolve_field(field)
803 def _force_resolve(self, item, allow_unknown=False):
804 if isinstance(item, Unresolved):
805 if item.target in self._private_internal_types:
808 return self._transformer.gtypename_to_giname(item.target,
812 print "WARNING: Skipping unknown interface %s" % \
817 if item in self._private_internal_types:
821 def _resolve_glib_interface(self, node):
822 node.parent = self._force_resolve(node.parent)
823 self._resolve_methods(node.methods)
824 self._resolve_properties(node.properties, node)
825 self._resolve_signals(node.signals)
826 node.prerequisites = filter(None,
827 [self._force_resolve(x, allow_unknown=True)
828 for x in node.prerequisites])
830 def _resolve_glib_object(self, node):
831 # If we can't find the parent class, just drop back to GObject.
832 # This supports hidden parent classes.
833 # http://bugzilla.gnome.org/show_bug.cgi?id=561360
835 node.parent = self._force_resolve(node.parent)
837 #print ("WARNING: Parent %r of class %r" +\
838 # " not found; using GObject") % (node.parent.target,
840 node.parent = self._transformer.gtypename_to_giname("GObject",
842 node.interfaces = filter(None,
843 [self._force_resolve(x, allow_unknown=True)
844 for x in node.interfaces])
845 self._resolve_constructors(node.constructors)
846 self._resolve_methods(node.methods)
847 self._resolve_methods(node.static_methods)
848 self._resolve_properties(node.properties, node)
849 self._resolve_signals(node.signals)
850 for field in node.fields:
851 self._resolve_field(field)
853 def _resolve_glib_boxed(self, node):
854 self._resolve_constructors(node.constructors)
855 self._resolve_methods(node.methods)
857 def _resolve_constructors(self, constructors):
858 for ctor in constructors:
859 self._resolve_function(ctor)
861 def _resolve_methods(self, methods):
862 for method in methods:
863 self._resolve_function(method)
865 def _resolve_signals(self, signals):
866 for signal in signals:
867 self._resolve_function(signal)
869 def _resolve_properties(self, properties, context):
871 for prop in properties:
873 self._resolve_property(prop)
877 #print ("WARNING: Deleting object property %r (of %r) "
878 # "with unknown type") % (fail, context)
879 properties.remove(fail)
881 def _resolve_property(self, prop):
882 prop.type = self._resolve_param_type(prop.type, allow_invalid=False)
884 def _adjust_throws(self, func):
885 if func.parameters == []:
888 last_param = func.parameters.pop()
890 if (last_param.type.name == 'GLib.Error' or
891 (self._namespace_name == 'GLib' and
892 last_param.type.name == 'Error')):
895 func.parameters.append(last_param)
897 def _resolve_function(self, func):
898 self._resolve_parameters(func.parameters)
899 func.retval.type = self._resolve_param_type(func.retval.type)
900 self._adjust_throws(func)
902 def _resolve_parameters(self, parameters):
903 for parameter in parameters:
904 parameter.type = self._resolve_param_type(parameter.type)
906 def _resolve_field(self, field):
907 if isinstance(field, Callback):
908 self._resolve_function(field)
909 elif isinstance(field, Record): # non-typedef'd struct
910 self._resolve_record(field)
911 elif isinstance(field, Union): # non-typedef'd union
912 self._resolve_union(field)
914 field.type = self._resolve_param_type(field.type)
916 def _resolve_alias(self, alias):
917 alias.target = self._resolve_type_name(alias.target, alias.target)
921 def _validate(self, nodes):
922 nodes = list(self._names.names.itervalues())
924 self._validating = True
928 #print "Type resolution; pass=%d" % (i, )
929 nodes = list(self._names.names.itervalues())
932 self._resolve_node(node)
933 except UnknownTypeError, e:
934 print "WARNING: %s: Deleting %r" % (e, node)
935 self._remove_attribute(node.name)
936 if len(nodes) == initlen:
939 self._print_statistics()
940 self._validating = False