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, 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 = []
94 self._failed_types = {}
95 self._boxed_types = {}
96 self._private_internal_types = {}
97 self._validating = False
101 def set_introspection_binary(self, binary):
102 self._binary = binary
104 def _print_statistics(self):
105 nodes = list(self._names.names.itervalues())
107 def count_type(otype):
108 return len([x for x in nodes
109 if isinstance(x[1], otype)])
110 objectcount = count_type(GLibObject)
111 ifacecount = count_type(GLibInterface)
112 enumcount = count_type(GLibEnum)
113 print " %d nodes; %d objects, %d interfaces, %d enums" \
114 % (len(nodes), objectcount, ifacecount, enumcount)
117 namespace = self._transformer.parse()
118 self._namespace_name = namespace.name
120 # First pass: parsing
121 for node in namespace.nodes:
122 self._parse_node(node)
124 # We don't want an alias for this - it's handled specially in
125 # the typelib compiler.
126 if namespace.name == 'GObject':
127 del self._names.aliases['Type']
129 # Get all the GObject data by passing our list of get_type
130 # functions to the compiled binary
132 self._execute_binary()
134 # Introspection is done from within parsing
136 # Second pass: pair boxed structures
137 for boxed in self._boxed_types.itervalues():
138 self._pair_boxed_type(boxed)
139 # Third pass: delete class structures, resolve
140 # all types we now know about
141 nodes = list(self._names.names.itervalues())
142 for (ns, node) in nodes:
144 self._resolve_node(node)
146 print "WARNING: DELETING node %s: %s" % (node.name, e)
147 self._remove_attribute(node.name)
148 # associate GtkButtonClass with GtkButton
149 if isinstance(node, Record):
150 self._pair_class_record(node)
151 for (ns, alias) in self._names.aliases.itervalues():
152 self._resolve_alias(alias)
154 self._print_statistics()
155 # Fourth pass: ensure all types are known
156 if not self._noclosure:
157 self._validate(nodes)
159 # Create a new namespace with what we found
160 namespace = Namespace(namespace.name, namespace.version)
161 namespace.nodes = map(lambda x: x[1], self._names.aliases.itervalues())
162 for (ns, x) in self._names.names.itervalues():
163 namespace.nodes.append(x)
168 def _add_attribute(self, node, replace=False):
169 node_name = node.name
170 if (not replace) and node_name in self._names.names:
172 self._names.names[node_name] = (None, node)
174 def _remove_attribute(self, name):
175 del self._names.names[name]
177 def _get_attribute(self, name):
178 node = self._names.names.get(name)
183 def _lookup_node(self, name):
184 if name in type_names:
186 node = self._get_attribute(name)
188 node = self._transformer.get_names().names.get(name)
193 def _register_internal_type(self, type_name, node):
194 self._names.type_names[type_name] = (None, node)
195 uscored = to_underscores(type_name).lower()
196 self._uscore_type_names[uscored] = node
197 # Besides the straight underscore conversion, we also try
198 # removing the underscores from the namespace as a possible C
199 # mapping; e.g. it's webkit_web_view, not web_kit_web_view
200 suffix = self._transformer.remove_prefix(type_name)
201 prefix = type_name[:-len(suffix)]
202 no_uscore_prefixed = (prefix + '_' + to_underscores(suffix)).lower()
203 self._uscore_type_names[no_uscore_prefixed] = node
207 def _resolve_gtypename(self, gtype_name):
209 return self._transformer.gtypename_to_giname(gtype_name,
212 return Unresolved(gtype_name)
214 def _execute_binary(self):
215 in_path = os.path.join(self._binary.tmpdir, 'types.txt')
216 f = open(in_path, 'w')
217 for func in self._get_type_functions:
221 out_path = os.path.join(self._binary.tmpdir, 'dump.xml')
224 args.extend(self._binary.args)
225 args.append('--introspect-dump=%s,%s' % (in_path, out_path))
227 # Invoke the binary, having written our get_type functions to types.txt
229 subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
230 except subprocess.CalledProcessError, e:
232 self._read_introspect_dump(out_path)
234 # Clean up temporaries
235 shutil.rmtree(self._binary.tmpdir)
237 def _read_introspect_dump(self, xmlpath):
238 from xml.etree.cElementTree import parse
239 tree = parse(xmlpath)
240 root = tree.getroot()
242 self._gtype_data[child.attrib['name']] = child
244 self._introspect_type(child)
246 def _create_gobject(self, node):
247 type_name = 'G' + node.name
248 if type_name == 'GObject':
251 elif type_name == 'GInitiallyUnowned':
252 parent_type_name = 'GObject'
253 parent_gitype = self._resolve_gtypename(parent_type_name)
254 symbol = 'g_initially_unowned_get_type'
255 gnode = GLibObject(node.name, parent_gitype, type_name, symbol, True)
256 gnode.fields.extend(node.fields)
257 self._add_attribute(gnode)
258 self._register_internal_type(type_name, gnode)
262 def _parse_node(self, node):
263 if isinstance(node, Enum):
264 self._parse_enum(node)
265 elif isinstance(node, Bitfield):
266 self._parse_bitfield(node)
267 elif isinstance(node, Function):
268 self._parse_function(node)
269 elif isinstance(node, Record):
270 self._parse_record(node)
271 elif isinstance(node, Callback):
272 self._parse_callback(node)
273 elif isinstance(node, Alias):
274 self._parse_alias(node)
275 elif isinstance(node, Member):
276 # FIXME: atk_misc_instance singletons
278 elif isinstance(node, Union):
279 self._parse_union(node)
280 elif isinstance(node, Constant):
281 self._parse_constant(node)
283 print 'GLIB Transformer: Unhandled node:', node
285 def _parse_alias(self, alias):
286 self._names.aliases[alias.name] = (None, alias)
288 def _parse_enum(self, enum):
289 self._add_attribute(enum)
291 def _parse_bitfield(self, enum):
292 self._add_attribute(enum)
294 def _parse_constant(self, constant):
295 self._add_attribute(constant)
297 def _parse_function(self, func):
298 if func.symbol in SYMBOL_BLACKLIST:
300 if func.symbol.startswith('_'):
302 for regexp in SYMBOL_BLACKLIST_RE:
303 if regexp.match(func.symbol):
305 if self._parse_get_type_function(func):
308 self._add_attribute(func)
310 def _parse_get_type_function(self, func):
312 if not symbol.endswith('_get_type'):
314 if self._namespace_name == 'GLib':
315 # No GObjects in GLib
319 # GType *_get_type(void)
320 if func.retval.type.name not in ['Type',
324 print ("Warning: *_get_type function returns '%r'"
325 ", not GObject.Type") % (func.retval.type.name, )
328 self._get_type_functions.append(symbol)
331 def _name_is_internal_gtype(self, giname):
333 node = self._get_attribute(giname)
334 return isinstance(node, (GLibObject, GLibInterface,
335 GLibBoxed, GLibEnum, GLibFlags))
339 def _parse_static_method(self, func):
340 components = func.symbol.split('_')
341 if len(components) < 2:
344 prefix_components = None
346 for i in xrange(1, len(components)-1):
347 prefix_components = '_'.join(components[0:-i])
348 methname = '_'.join(components[-i:])
349 target_klass = self._uscore_type_names.get(prefix_components)
350 if target_klass and isinstance(target_klass, GLibObject):
355 self._remove_attribute(func.name)
357 target_klass.static_methods.append(func)
358 func.is_method = True
361 def _parse_method(self, func):
362 if not func.parameters:
364 return self._parse_method_common(func, True)
366 def _parse_constructor(self, func):
367 return self._parse_method_common(func, False)
369 def _parse_method_common(self, func, is_method):
370 # Skip _get_type functions, we processed them
372 if func.symbol.endswith('_get_type'):
374 if self._namespace_name == 'GLib':
375 # No GObjects in GLib
379 target_arg = func.retval
381 target_arg = func.parameters[0]
384 # Methods require their first arg to be a known class
385 # Look at the original C type (before namespace stripping), without
386 # pointers: GtkButton -> gtk_button_, so we can figure out the
388 argtype = target_arg.type.ctype.replace('*', '')
389 name = self._transformer.remove_prefix(argtype)
390 name_uscore = to_underscores_noprefix(name).lower()
391 name_offset = func.symbol.find(name_uscore)
394 prefix = func.symbol[:name_offset+len(name_uscore)]
396 # Constructors must have _new
397 # Take everything before that as class name
398 new_idx = func.symbol.find('_new')
401 # Constructors don't return basic types
402 derefed = self._transformer.follow_aliases(target_arg.type.name,
404 if derefed in type_names:
405 #print "NOTE: Rejecting constructor returning basic: %r" \
408 prefix = func.symbol[:new_idx]
410 klass = self._uscore_type_names.get(prefix)
412 #print "NOTE: No valid matching class for likely "+\
413 # "method or constructor: %r" % (func.symbol, )
415 # Enums can't have ctors or methods
416 if isinstance(klass, (GLibEnum, GLibFlags)):
419 # The _uscore_type_names member holds the plain GLibBoxed
420 # object; we want to actually use the struct/record associated
421 if isinstance(klass, (Record, Union)):
422 remove_prefix = klass.symbol
424 remove_prefix = klass.type_name
426 name = self._transformer.remove_prefix(remove_prefix)
427 klass = self._get_attribute(name)
432 # Interfaces can't have constructors, punt to global scope
433 if isinstance(klass, GLibInterface):
434 #print "NOTE: Rejecting constructor for"+\
435 # " interface type: %r" % (func.symbol, )
437 # TODO - check that the return type is a subclass of the
438 # class from the prefix
439 # But for now, ensure that constructor returns are always
440 # the most concrete class
441 name = self._transformer.remove_prefix(remove_prefix)
442 func.retval.type = Type(name, func.retval.type.ctype)
444 self._remove_attribute(func.name)
445 # Strip namespace and object prefix: gtk_window_new -> new
446 func.name = func.symbol[len(prefix)+1:]
448 # We don't need the "this" parameter
449 del func.parameters[0]
450 klass.methods.append(func)
451 func.is_method = True
453 klass.constructors.append(func)
456 def _parse_record(self, record):
457 # This is a hack, but GObject is a rather fundamental piece so.
458 internal_names = ["Object", 'InitiallyUnowned']
459 g_internal_names = ["G" + x for x in internal_names]
460 if (self._namespace_name == 'GObject' and
461 record.name in internal_names):
462 self._create_gobject(record)
464 elif record.name in g_internal_names:
467 node = self._names.names.get(record.name)
469 self._add_attribute(record, replace=True)
470 self._register_internal_type(record.symbol, record)
473 node.fields = record.fields[:]
475 def _parse_union(self, union):
476 node = self._names.names.get(union.name)
478 self._add_attribute(union, replace=True)
479 self._register_internal_type(union.symbol, union)
482 node.fields = union.fields[:]
484 def _parse_callback(self, callback):
485 self._add_attribute(callback)
487 def _strip_class_suffix(self, name):
488 if (name.endswith('Class') or
489 name.endswith('Iface')):
491 elif name.endswith('Interface'):
496 def _arg_is_failed(self, param):
497 ctype = self._transformer.ctype_of(param).replace('*', '')
498 uscored = to_underscores(self._strip_class_suffix(ctype)).lower()
499 if uscored in self._failed_types:
500 print "Warning: failed type: %r" % (param, )
504 def _pair_class_record(self, maybe_class):
505 name = self._strip_class_suffix(maybe_class.name)
506 if name == maybe_class.name:
509 if self._arg_is_failed(maybe_class):
510 print "WARNING: deleting no-type %r" % (maybe_class.name, )
511 del self._names.names[maybe_class.name]
514 # Object class fields are assumed to be read-only
515 # (see also _introspect_object and transformer.py)
516 for field in maybe_class.fields:
517 if isinstance(field, Field):
518 field.writable = False
520 name = self._resolve_type_name(name)
521 resolved = self._transformer.remove_prefix(name)
522 pair_class = self._get_attribute(resolved)
523 if pair_class and isinstance(pair_class, GLibInterface):
524 for field in maybe_class.fields[1:]:
525 pair_class.fields.append(field)
527 name = self._transformer.remove_prefix(maybe_class.name)
528 pair_class = self._get_attribute(name)
529 if pair_class and isinstance(pair_class,
530 (GLibObject, GLibInterface)):
532 del self._names.names[maybe_class.name]
536 def _introspect_type(self, xmlnode):
537 if xmlnode.tag in ('enum', 'flags'):
538 self._introspect_enum(xmlnode)
539 elif xmlnode.tag == 'class':
540 self._introspect_object(xmlnode)
541 elif xmlnode.tag == 'interface':
542 self._introspect_interface(xmlnode)
543 elif xmlnode.tag == 'boxed':
544 self._introspect_boxed(xmlnode)
546 raise ValueError("Unhandled introspection XML tag %s", xmlnode.tag)
548 def _introspect_enum(self, node):
550 for member in node.findall('member'):
551 members.append(GLibEnumMember(member.attrib['nick'],
552 member.attrib['value'],
553 member.attrib['name'],
554 member.attrib['nick']))
556 klass = (GLibFlags if node.tag == 'flags' else GLibEnum)
557 type_name = node.attrib['name']
558 enum_name = self._transformer.remove_prefix(type_name)
559 node = klass(enum_name, type_name, members, node.attrib['get-type'])
560 self._add_attribute(node, replace=True)
561 self._register_internal_type(type_name, node)
563 def _introspect_object(self, xmlnode):
564 type_name = xmlnode.attrib['name']
565 # We handle this specially above; in 2.16 and below there
566 # was no g_object_get_type, for later versions we need
568 if type_name == 'GObject':
570 parent_type_name = xmlnode.attrib['parent']
571 parent_gitype = self._resolve_gtypename(parent_type_name)
572 is_abstract = not not xmlnode.attrib.get('abstract', False)
574 self._transformer.remove_prefix(type_name),
577 xmlnode.attrib['get-type'], is_abstract)
578 self._introspect_properties(node, xmlnode)
579 self._introspect_signals(node, xmlnode)
580 self._introspect_implemented_interfaces(node, xmlnode)
583 record = self._get_attribute(node.name)
584 if record is not None:
585 node.fields = record.fields
586 for field in node.fields:
587 if isinstance(field, Field):
588 # Object instance fields are assumed to be read-only
589 # (see also _pair_class_record and transformer.py)
590 field.writable = False
592 self._add_attribute(node, replace=True)
593 self._register_internal_type(type_name, node)
595 def _introspect_interface(self, xmlnode):
596 type_name = xmlnode.attrib['name']
597 node = GLibInterface(
598 self._transformer.remove_prefix(type_name),
600 type_name, xmlnode.attrib['get-type'])
601 self._introspect_properties(node, xmlnode)
602 self._introspect_signals(node, xmlnode)
603 for child in xmlnode.findall('prerequisite'):
604 name = child.attrib['name']
605 prereq = self._resolve_gtypename(name)
606 node.prerequisites.append(prereq)
607 # GtkFileChooserEmbed is an example of a private interface, we
608 # just filter them out
609 if xmlnode.attrib['get-type'].startswith('_'):
610 print "NOTICE: Marking %s as internal type" % (type_name, )
611 self._private_internal_types[type_name] = node
613 self._add_attribute(node, replace=True)
614 self._register_internal_type(type_name, node)
616 def _introspect_boxed(self, xmlnode):
617 type_name = xmlnode.attrib['name']
618 # This one doesn't go in the main namespace; we associate it with
619 # the struct or union
620 node = GLibBoxed(type_name, xmlnode.attrib['get-type'])
621 self._boxed_types[node.type_name] = node
622 self._register_internal_type(type_name, node)
624 def _introspect_implemented_interfaces(self, node, xmlnode):
626 for interface in xmlnode.findall('implements'):
627 gitype = self._resolve_gtypename(interface.attrib['name'])
628 gt_interfaces.append(gitype)
629 node.interfaces = gt_interfaces
631 def _introspect_properties(self, node, xmlnode):
632 for pspec in xmlnode.findall('property'):
633 ctype = pspec.attrib['type']
634 flags = int(pspec.attrib['flags'])
635 readable = (flags & G_PARAM_READABLE) != 0
636 writable = (flags & G_PARAM_WRITABLE) != 0
637 construct = (flags & G_PARAM_CONSTRUCT) != 0
638 construct_only = (flags & G_PARAM_CONSTRUCT_ONLY) != 0
639 node.properties.append(Property(
640 pspec.attrib['name'],
641 type_name_from_ctype(ctype),
642 readable, writable, construct, construct_only,
646 def _introspect_signals(self, node, xmlnode):
647 for signal_info in xmlnode.findall('signal'):
648 rctype = signal_info.attrib['return']
649 rtype = Type(self._transformer.parse_ctype(rctype), rctype)
650 return_ = Return(rtype, signal_info.attrib['return'])
651 return_.transfer = PARAM_TRANSFER_FULL
652 signal = GLibSignal(signal_info.attrib['name'], return_)
653 for i, parameter in enumerate(signal_info.findall('param')):
657 name = 'p%s' % (i-1, )
658 pctype = parameter.attrib['type']
659 ptype = Type(self._transformer.parse_ctype(pctype), pctype)
660 param = Parameter(name, ptype)
661 param.transfer = 'none'
662 signal.parameters.append(param)
663 node.signals.append(signal)
667 def _resolve_type_name(self, type_name, ctype=None):
668 # Workaround glib bug #548689, to be included in 2.18.0
669 if type_name == "GParam":
670 type_name = "GObject.ParamSpec"
671 res = self._transformer.resolve_type_name_full
673 return res(type_name, ctype, self._names)
675 return self._transformer.resolve_type_name(type_name, ctype)
677 def _resolve_param_type(self, ptype, **kwargs):
678 # Workaround glib bug #548689, to be included in 2.18.0
679 if ptype.name == "GParam":
680 ptype.name = "GObject.ParamSpec"
681 return self._transformer.resolve_param_type_full(ptype,
685 def _resolve_node(self, node):
686 if isinstance(node, Function):
687 self._resolve_function_toplevel(node)
689 elif isinstance(node, Callback):
690 self._resolve_function(node)
691 elif isinstance(node, GLibObject):
692 self._resolve_glib_object(node)
693 elif isinstance(node, GLibInterface):
694 self._resolve_glib_interface(node)
695 elif isinstance(node, Record):
696 self._resolve_record(node)
697 elif isinstance(node, Union):
698 self._resolve_union(node)
699 elif isinstance(node, Alias):
700 self._resolve_alias(node)
702 def _resolve_function_toplevel(self, func):
703 for parser in [self._parse_constructor,
705 self._parse_static_method]:
706 newfunc = parser(func)
708 self._resolve_function(newfunc)
710 self._resolve_function(func)
712 def _pair_boxed_type(self, boxed):
713 name = self._transformer.remove_prefix(boxed.type_name)
714 pair_node = self._get_attribute(name)
716 boxed_item = GLibBoxedOther(name, boxed.type_name,
718 elif isinstance(pair_node, Record):
719 boxed_item = GLibBoxedStruct(pair_node.name, boxed.type_name,
721 boxed_item.fields = pair_node.fields
722 elif isinstance(pair_node, Union):
723 boxed_item = GLibBoxedUnion(pair_node.name, boxed.type_name,
725 boxed_item.fields = pair_node.fields
728 self._add_attribute(boxed_item, replace=True)
730 def _resolve_record(self, node):
731 for field in node.fields:
732 self._resolve_field(field)
734 def _resolve_union(self, node):
735 for field in node.fields:
736 self._resolve_field(field)
738 def _force_resolve(self, item, allow_unknown=False):
739 if isinstance(item, Unresolved):
740 if item.target in self._private_internal_types:
743 return self._transformer.gtypename_to_giname(item.target,
747 print "WARNING: Skipping unknown interface %s" % \
752 if item in self._private_internal_types:
756 def _resolve_glib_interface(self, node):
757 node.parent = self._force_resolve(node.parent)
758 self._resolve_methods(node.methods)
759 self._resolve_properties(node.properties, node)
760 self._resolve_signals(node.signals)
761 node.prerequisites = filter(None,
762 [self._force_resolve(x, allow_unknown=True)
763 for x in node.prerequisites])
765 def _resolve_glib_object(self, node):
766 node.parent = self._force_resolve(node.parent)
767 node.interfaces = filter(None,
768 [self._force_resolve(x, allow_unknown=True)
769 for x in node.interfaces])
770 self._resolve_constructors(node.constructors)
771 self._resolve_methods(node.methods)
772 self._resolve_methods(node.static_methods)
773 self._resolve_properties(node.properties, node)
774 self._resolve_signals(node.signals)
775 for field in node.fields:
776 self._resolve_field(field)
778 def _resolve_glib_boxed(self, node):
779 self._resolve_constructors(node.constructors)
780 self._resolve_methods(node.methods)
782 def _resolve_constructors(self, constructors):
783 for ctor in constructors:
784 self._resolve_function(ctor)
786 def _resolve_methods(self, methods):
787 for method in methods:
788 self._resolve_function(method)
790 def _resolve_signals(self, signals):
791 for signal in signals:
792 self._resolve_function(signal)
794 def _resolve_properties(self, properties, context):
796 for prop in properties:
798 self._resolve_property(prop)
802 print ("WARNING: Deleting object property %r (of %r) "
803 "with unknown type") % (fail, context)
804 properties.remove(fail)
806 def _resolve_property(self, prop):
807 prop.type = self._resolve_param_type(prop.type, allow_invalid=False)
809 def _adjust_throws(self, func):
810 if func.parameters == []:
813 last_param = func.parameters.pop()
815 if (last_param.type.name == 'GLib.Error' or
816 (self._namespace_name == 'GLib' and
817 last_param.type.name == 'Error')):
820 func.parameters.append(last_param)
822 def _resolve_function(self, func):
823 self._resolve_parameters(func.parameters)
824 func.retval.type = self._resolve_param_type(func.retval.type)
825 self._adjust_throws(func)
827 def _resolve_parameters(self, parameters):
828 for parameter in parameters:
829 parameter.type = self._resolve_param_type(parameter.type)
831 def _resolve_field(self, field):
832 if isinstance(field, Callback):
833 self._resolve_function(field)
835 field.type = self._resolve_param_type(field.type)
837 def _resolve_alias(self, alias):
838 alias.target = self._resolve_type_name(alias.target, alias.target)
842 def _validate(self, nodes):
843 nodes = list(self._names.names.itervalues())
845 self._validating = True
849 print "Type resolution; pass=%d" % (i, )
850 nodes = list(self._names.names.itervalues())
853 self._resolve_node(node)
854 except UnknownTypeError, e:
855 print "WARNING: %s: Deleting %r" % (e, node)
856 self._remove_attribute(node.name)
857 if len(nodes) == initlen:
860 self._print_statistics()
861 self._validating = False