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.
26 from .config import DATADIR, GIR_DIR, GIR_SUFFIX
27 from .girparser import GIRParser
28 from .sourcescanner import (
29 SourceSymbol, ctype_name, CTYPE_POINTER,
30 CTYPE_BASIC_TYPE, CTYPE_UNION, CTYPE_ARRAY, CTYPE_TYPEDEF,
31 CTYPE_VOID, CTYPE_ENUM, CTYPE_FUNCTION, CTYPE_STRUCT,
32 CSYMBOL_TYPE_FUNCTION, CSYMBOL_TYPE_TYPEDEF, CSYMBOL_TYPE_STRUCT,
33 CSYMBOL_TYPE_ENUM, CSYMBOL_TYPE_UNION, CSYMBOL_TYPE_OBJECT,
34 CSYMBOL_TYPE_MEMBER, CSYMBOL_TYPE_ELLIPSIS, CSYMBOL_TYPE_CONST,
37 class TypeResolutionException(Exception):
40 _xdg_data_dirs = [x for x in os.environ.get('XDG_DATA_DIRS', '').split(':') \
41 + [DATADIR, '/usr/share'] if x]
43 class Transformer(object):
44 namespace = property(lambda self: self._namespace)
46 UCASE_CONSTANT_RE = re.compile(r'[_A-Z0-9]+')
48 def __init__(self, cachestore, namespace_name, namespace_version,
49 identifier_prefixes=None, symbol_prefixes=None):
50 self._cwd = os.getcwd() + os.sep
51 self._cachestore = cachestore
53 self._namespace = ast.Namespace(namespace_name, namespace_version,
54 identifier_prefixes=identifier_prefixes,
55 symbol_prefixes=symbol_prefixes)
56 self._pkg_config_packages = set()
57 self._typedefs_ns = {}
58 self._enable_warnings = False
61 self._include_names = set()
62 self._includepaths = []
64 def get_includes(self):
65 return self._include_names
67 def enable_warnings(self, enable):
68 self._enable_warnings = enable
73 def get_pkgconfig_packages(self):
74 return self._pkg_config_packages
76 def set_source_ast(self, src_ast):
77 self.generator = src_ast
79 def _append_new_node(self, node):
80 original = self._namespace.get(node.name)
81 # Special case constants here; we allow duplication to sort-of
82 # handle #ifdef. But this introduces an arch-dependency in the .gir
83 # file. So far this has only come up scanning glib - in theory, other
84 # modules will just depend on that.
85 if isinstance(original, ast.Constant) and isinstance(node, ast.Constant):
89 positions.update(original.file_positions)
90 positions.update(node.file_positions)
91 self.log_warning("Namespace conflict for '%s'" % (node.name, ),
92 positions, fatal=True)
94 self._namespace.append(node)
97 for symbol in self.generator.get_symbols():
98 node = self._traverse_one(symbol)
100 self._append_new_node(node)
102 # Now look through the namespace for things like
103 # typedef struct _Foo Foo;
104 # where we've never seen the struct _Foo. Just create
105 # an empty structure for these as "disguised"
106 # If we do have a class/interface, merge fields
107 for typedef, compound in self._typedefs_ns.iteritems():
108 ns_compound = self._namespace.get(compound.name)
110 ns_compound = self._namespace.get('_' + compound.name)
111 if (not ns_compound and isinstance(compound, (ast.Record, ast.Union))
112 and len(compound.fields) == 0):
113 disguised = ast.Record(compound.name, typedef, disguised=True)
114 self._namespace.append(disguised)
115 elif not ns_compound:
116 self._namespace.append(compound)
117 elif isinstance(ns_compound, (ast.Record, ast.Union)) and len(ns_compound.fields) == 0:
118 ns_compound.fields = compound.fields
119 self._typedefs_ns = None
121 def set_include_paths(self, paths):
122 self._includepaths = list(paths)
124 def register_include(self, include):
125 if include in self._include_names:
127 filename = self._find_include(include)
128 self._parse_include(filename)
129 self._include_names.add(include)
131 def lookup_giname(self, name):
132 """Given a name of the form Foo or Bar.Foo,
133 return the corresponding ast.Node, or None if none
134 available. Will throw KeyError however for unknown
137 return self._namespace.get(name)
139 (ns, name) = name.split('.', 1)
140 if ns == self._namespace.name:
141 return self._namespace.get(name)
142 include = self._includes[ns]
143 return include.get(name)
145 def lookup_typenode(self, typeobj):
146 """Given a Type object, if it points to a giname,
147 calls lookup_giname() on the name. Otherwise return
149 if typeobj.target_giname:
150 return self.lookup_giname(typeobj.target_giname)
155 def log_warning(self, text, file_positions=None, prefix=None,
157 """Log a warning, using optional file positioning information.
158 If the warning is related to a ast.Node type, see log_node_warning()."""
159 if not fatal and not self._enable_warnings:
164 if file_positions is None or len(file_positions) == 0:
165 target_file_positions = [('<unknown>', -1, -1)]
167 target_file_positions = file_positions
169 position_strings = []
170 for (filename, line, column) in target_file_positions:
171 if filename.startswith(self._cwd):
172 filename = filename[len(self._cwd):]
174 position = '%s:%d:%d' % (filename, line, column)
176 position = '%s:%d' % (filename, line, )
178 position = '%s:' % (filename, )
179 position_strings.append(position)
181 for position in position_strings[:-1]:
182 print >>sys.stderr, "%s:" % (position, )
183 last_position = position_strings[-1]
184 error_type = 'error' if fatal else 'warning'
186 print >>sys.stderr, \
187 '''%s: %s: %s: %s: %s''' % (last_position, error_type, self._namespace.name,
190 print >>sys.stderr, \
191 '''%s: %s: %s: %s''' % (last_position, error_type, self._namespace.name, text)
195 def log_symbol_warning(self, symbol, text, **kwargs):
196 """Log a warning in the context of the given symbol."""
197 if symbol.source_filename:
198 file_positions = [(symbol.source_filename, symbol.line, -1)]
200 file_positions = None
201 prefix = "symbol=%r" % (symbol.ident, )
202 self.log_warning(text, file_positions, prefix=prefix, **kwargs)
204 def log_node_warning(self, node, text, context=None, fatal=False):
205 """Log a warning, using information about file positions from
206 the given node. The optional context argument, if given, should be
207 another ast.Node type which will also be displayed. If no file position
208 information is available from the node, the position data from the
209 context will be used."""
210 if hasattr(node, 'file_positions'):
211 if (len(node.file_positions) == 0 and
212 (context is not None) and len(context.file_positions) > 0):
213 file_positions = context.file_positions
215 file_positions = node.file_positions
217 file_positions = None
219 text = "context=%r %s" % (node, text)
222 if isinstance(context, ast.Function):
223 name = context.symbol
226 text = "%s: %s" % (name, text)
227 elif len(file_positions) == 0 and hasattr(node, 'name'):
228 text = "(%s)%s: %s" % (node.__class__.__name__, node.name, text)
230 self.log_warning(text, file_positions, fatal=fatal)
232 def _find_include(self, include):
233 searchdirs = self._includepaths[:]
234 for path in _xdg_data_dirs:
235 searchdirs.append(os.path.join(path, GIR_SUFFIX))
236 searchdirs.append(GIR_DIR)
238 girname = '%s-%s.gir' % (include.name, include.version)
240 path = os.path.join(d, girname)
241 if os.path.exists(path):
243 sys.stderr.write("Couldn't find include %r (search path: %r)\n"\
244 % (girname, searchdirs))
247 def _parse_include(self, filename):
248 parser = self._cachestore.load(filename)
251 parser.parse(filename)
252 self._cachestore.store(filename, parser)
254 for include in parser.get_includes():
255 self.register_include(include)
257 for pkg in parser.get_pkgconfig_packages():
258 self._pkg_config_packages.add(pkg)
259 namespace = parser.get_namespace()
260 self._includes[namespace.name] = namespace
262 def _iter_namespaces(self):
263 """Return an iterator over all included namespaces; the
264 currently-scanned namespace is first."""
265 yield self._namespace
266 for ns in self._includes.itervalues():
269 def _sort_matches(self, x, y):
270 if x[0] is self._namespace:
272 elif y[0] is self._namespace:
274 return cmp(x[2], y[2])
276 def split_ctype_namespaces(self, ident):
277 """Given a StudlyCaps string identifier like FooBar, return a
278 list of (namespace, stripped_identifier) sorted by namespace length,
279 or raise ValueError. As a special case, if the current namespace matches,
280 it is always biggest (i.e. last)."""
282 for ns in self._iter_namespaces():
283 for prefix in ns.identifier_prefixes:
284 if ident.startswith(prefix):
285 matches.append((ns, ident[len(prefix):], len(prefix)))
288 matches.sort(self._sort_matches)
289 return map(lambda x: (x[0], x[1]), matches)
290 raise ValueError("Unknown namespace for identifier %r" % (ident, ))
292 def split_csymbol(self, symbol):
293 """Given a C symbol like foo_bar_do_baz, return a pair of
294 (namespace, stripped_symbol) or raise ValueError."""
296 for ns in self._iter_namespaces():
297 for prefix in ns.symbol_prefixes:
298 if not prefix.endswith('_'):
299 prefix = prefix + '_'
300 if symbol.startswith(prefix):
301 matches.append((ns, symbol[len(prefix):], len(prefix)))
304 matches.sort(self._sort_matches)
305 return (matches[-1][0], matches[-1][1])
306 raise ValueError("Unknown namespace for symbol %r" % (symbol, ))
308 def strip_identifier_or_warn(self, ident, fatal=False):
309 hidden = ident.startswith('_')
313 matches = self.split_ctype_namespaces(ident)
314 except ValueError, e:
315 self.log_warning(str(e), fatal=fatal)
317 for ns, name in matches:
318 if ns is self._namespace:
322 (ns, name) = matches[-1]
323 self.log_warning("Skipping foreign identifier %r from namespace %s" % (ident, ns.name, ),
327 def _strip_symbol_or_warn(self, symbol, is_constant=False, fatal=False):
330 # Temporarily lowercase
331 ident = ident.lower()
332 hidden = ident.startswith('_')
336 (ns, name) = self.split_csymbol(ident)
337 except ValueError, e:
338 self.log_symbol_warning(symbol, "Unknown namespace", fatal=fatal)
340 if ns != self._namespace:
341 self.log_symbol_warning(symbol,
342 "Skipping foreign symbol from namespace %s" % (ns.name, ),
351 def _traverse_one(self, symbol, stype=None):
352 assert isinstance(symbol, SourceSymbol), symbol
356 if stype == CSYMBOL_TYPE_FUNCTION:
357 return self._create_function(symbol)
358 elif stype == CSYMBOL_TYPE_TYPEDEF:
359 return self._create_typedef(symbol)
360 elif stype == CSYMBOL_TYPE_STRUCT:
361 return self._create_struct(symbol)
362 elif stype == CSYMBOL_TYPE_ENUM:
363 return self._create_enum(symbol)
364 elif stype == CSYMBOL_TYPE_MEMBER:
365 return self._create_member(symbol)
366 elif stype == CSYMBOL_TYPE_UNION:
367 return self._create_union(symbol)
368 elif stype == CSYMBOL_TYPE_CONST:
369 return self._create_const(symbol)
370 # Ignore variable declarations in the header
371 elif stype == CSYMBOL_TYPE_OBJECT:
374 print 'transformer: unhandled symbol: %r' % (symbol, )
376 def _enum_common_prefix(self, symbol):
377 def common_prefix(a, b):
379 for aword, bword in zip(a.split('_'), b.split('_')):
381 return '_'.join(commonparts) + '_'
382 commonparts.append(aword)
385 # Nothing less than 2 has a common prefix
386 if len(list(symbol.base_type.child_list)) < 2:
389 for child in symbol.base_type.child_list:
393 prefix = common_prefix(prefix, child.ident)
398 def _create_enum(self, symbol):
399 prefix = self._enum_common_prefix(symbol)
401 prefixlen = len(prefix)
405 for child in symbol.base_type.child_list:
407 name = child.ident[prefixlen:]
409 # Ok, the enum members don't have a consistent prefix
410 # among them, so let's just remove the global namespace
412 name = self._strip_symbol_or_warn(child, is_constant=True)
415 members.append(ast.Member(name.lower(),
419 enum_name = self.strip_identifier_or_warn(symbol.ident)
422 if symbol.base_type.is_bitfield:
426 node = klass(enum_name, symbol.ident, members)
427 node.add_symbol_reference(symbol)
430 def _create_function(self, symbol):
431 parameters = list(self._create_parameters(symbol.base_type))
432 return_ = self._create_return(symbol.base_type.base_type)
433 name = self._strip_symbol_or_warn(symbol)
436 func = ast.Function(name, return_, parameters, False, symbol.ident)
437 func.add_symbol_reference(symbol)
440 def _create_source_type(self, source_type):
441 if source_type is None:
443 if source_type.type == CTYPE_VOID:
445 elif source_type.type == CTYPE_BASIC_TYPE:
446 value = source_type.name
447 elif source_type.type == CTYPE_TYPEDEF:
448 value = source_type.name
449 elif source_type.type == CTYPE_ARRAY:
450 return self._create_source_type(source_type.base_type)
451 elif source_type.type == CTYPE_POINTER:
452 value = self._create_source_type(source_type.base_type) + '*'
457 def _create_parameters(self, base_type):
458 # warn if we see annotations for unknown parameters
459 param_names = set(child.ident for child in base_type.child_list)
460 for child in base_type.child_list:
461 yield self._create_parameter(child)
463 def _create_member(self, symbol):
464 source_type = symbol.base_type
465 if (source_type.type == CTYPE_POINTER and
466 symbol.base_type.base_type.type == CTYPE_FUNCTION):
467 node = self._create_callback(symbol, member=True)
468 elif source_type.type == CTYPE_STRUCT and source_type.name is None:
469 node = self._create_struct(symbol, anonymous=True)
470 elif source_type.type == CTYPE_UNION and source_type.name is None:
471 node = self._create_union(symbol, anonymous=True)
473 # Special handling for fields; we don't have annotations on them
474 # to apply later, yet.
475 if source_type.type == CTYPE_ARRAY:
476 ctype = self._create_source_type(source_type)
477 canonical_ctype = self._canonicalize_ctype(ctype)
478 if canonical_ctype[-1] == '*':
479 derefed_name = canonical_ctype[:-1]
481 derefed_name = canonical_ctype
482 ftype = ast.Array(None, self.create_type_from_ctype_string(ctype),
484 child_list = list(symbol.base_type.child_list)
485 ftype.zeroterminated = False
487 ftype.size = child_list[0].const_int
489 ftype = self._create_type_from_base(symbol.base_type)
490 # ast.Fields are assumed to be read-write
491 # (except for Objects, see also glibtransformer.py)
492 node = ast.Field(symbol.ident, ftype,
493 readable=True, writable=True, bits=symbol.const_int)
496 def _create_typedef(self, symbol):
497 ctype = symbol.base_type.type
498 if (ctype == CTYPE_POINTER and
499 symbol.base_type.base_type.type == CTYPE_FUNCTION):
500 node = self._create_typedef_callback(symbol)
501 elif (ctype == CTYPE_POINTER and
502 symbol.base_type.base_type.type == CTYPE_STRUCT):
503 node = self._create_typedef_struct(symbol, disguised=True)
504 elif ctype == CTYPE_STRUCT:
505 node = self._create_typedef_struct(symbol)
506 elif ctype == CTYPE_UNION:
507 node = self._create_typedef_union(symbol)
508 elif ctype == CTYPE_ENUM:
509 return self._create_enum(symbol)
510 elif ctype in (CTYPE_TYPEDEF,
514 name = self.strip_identifier_or_warn(symbol.ident)
517 if symbol.base_type.name:
518 target = self.create_type_from_ctype_string(symbol.base_type.name)
520 target = ast.TYPE_ANY
521 if name in ast.type_names:
523 return ast.Alias(name, target, ctype=symbol.ident)
525 raise NotImplementedError(
526 "symbol %r of type %s" % (symbol.ident, ctype_name(ctype)))
529 def _canonicalize_ctype(self, ctype):
530 # First look up the ctype including any pointers;
531 # a few type names like 'char*' have their own aliases
532 # and we need pointer information for those.
533 firstpass = ast.type_names.get(ctype)
535 # If we have a particular alias for this, skip deep
536 # canonicalization to prevent changing
537 # e.g. char* -> int8*
539 return firstpass.target_fundamental
541 if not ctype.endswith('*'):
544 # We have a pointer type.
545 # Strip the end pointer, canonicalize our base type
547 canonical_base = self._canonicalize_ctype(base)
549 # Append the pointer again
550 canonical = canonical_base + '*'
554 def parse_ctype(self, ctype, is_member=False):
555 canonical = self._canonicalize_ctype(ctype)
557 # Remove all pointers - we require standard calling
558 # conventions. For example, an 'int' is always passed by
559 # value (unless it's out or inout).
560 derefed_typename = canonical.replace('*', '')
562 # Preserve "pointerness" of struct/union members
563 if (is_member and canonical.endswith('*') and
564 derefed_typename in ast.basic_type_names):
567 return derefed_typename
569 def _create_type_from_base(self, source_type, is_parameter=False, is_return=False):
570 ctype = self._create_source_type(source_type)
571 const = ((source_type.type == CTYPE_POINTER) and
572 (source_type.base_type.type_qualifier & TYPE_QUALIFIER_CONST))
573 return self.create_type_from_ctype_string(ctype, is_const=const,
574 is_parameter=is_parameter, is_return=is_return)
576 def _create_bare_container_type(self, base, ctype=None,
578 if base in ('GList', 'GSList', 'GLib.List', 'GLib.SList'):
579 if base in ('GList', 'GSList'):
580 name = 'GLib.' + base[1:]
583 return ast.List(name, ast.TYPE_ANY, ctype=ctype,
585 elif base in ('GArray', 'GPtrArray', 'GByteArray',
586 'GLib.Array', 'GLib.PtrArray', 'GLib.ByteArray'):
587 if base in ('GArray', 'GPtrArray', 'GByteArray'):
588 name = 'GLib.' + base[1:]
591 return ast.Array(name, ast.TYPE_ANY, ctype=ctype,
593 elif base in ('GHashTable', 'GLib.HashTable'):
594 return ast.Map(ast.TYPE_ANY, ast.TYPE_ANY, ctype=ctype, is_const=is_const)
597 def create_type_from_ctype_string(self, ctype, is_const=False,
598 is_parameter=False, is_return=False):
599 canonical = self._canonicalize_ctype(ctype)
600 base = canonical.replace('*', '')
602 # Special default: char ** -> ast.Array, same for GStrv
603 if (is_return and canonical == 'utf8*') or base == 'GStrv':
604 bare_utf8 = ast.TYPE_STRING.clone()
605 bare_utf8.ctype = None
606 return ast.Array(None, bare_utf8, ctype=ctype,
609 fundamental = ast.type_names.get(base)
610 if fundamental is not None:
611 return ast.Type(target_fundamental=fundamental.target_fundamental,
614 container = self._create_bare_container_type(base, ctype=ctype, is_const=is_const)
617 return ast.Type(ctype=ctype, is_const=is_const)
619 def _create_parameter(self, symbol):
620 if symbol.type == CSYMBOL_TYPE_ELLIPSIS:
621 ptype = ast.Varargs()
623 ptype = self._create_type_from_base(symbol.base_type, is_parameter=True)
624 return ast.Parameter(symbol.ident, ptype)
626 def _create_return(self, source_type):
627 typeval = self._create_type_from_base(source_type, is_return=True)
628 return ast.Return(typeval)
630 def _create_const(self, symbol):
631 # Don't create constants for non-public things
632 # http://bugzilla.gnome.org/show_bug.cgi?id=572790
633 if (symbol.source_filename is None or
634 not symbol.source_filename.endswith('.h')):
636 # ignore non-uppercase defines
637 if not self.UCASE_CONSTANT_RE.match(symbol.ident):
639 name = self._strip_symbol_or_warn(symbol, is_constant=True)
642 if symbol.const_string is not None:
643 typeval = ast.TYPE_STRING
644 value = symbol.const_string
645 elif symbol.const_int is not None:
646 typeval = ast.TYPE_INT
647 value = '%d' % (symbol.const_int, )
648 elif symbol.const_double is not None:
649 typeval = ast.TYPE_DOUBLE
650 value = '%f' % (symbol.const_double, )
652 raise AssertionError()
654 const = ast.Constant(name, typeval, value)
655 const.add_symbol_reference(symbol)
658 def _create_typedef_struct(self, symbol, disguised=False):
659 name = self.strip_identifier_or_warn(symbol.ident)
662 struct = ast.Record(name, symbol.ident, disguised)
663 self._parse_fields(symbol, struct)
664 struct.add_symbol_reference(symbol)
665 self._typedefs_ns[symbol.ident] = struct
668 def _create_typedef_union(self, symbol):
669 name = self.strip_identifier_or_warn(symbol.ident)
672 union = ast.Union(name, symbol.ident)
673 self._parse_fields(symbol, union)
674 union.add_symbol_reference(symbol)
675 self._typedefs_ns[symbol.ident] = union
678 def _create_typedef_callback(self, symbol):
679 callback = self._create_callback(symbol)
682 self._typedefs_ns[callback.name] = callback
685 def _parse_fields(self, symbol, compound):
686 for child in symbol.base_type.child_list:
687 child_node = self._traverse_one(child)
690 if isinstance(child_node, ast.Field):
693 field = ast.Field(child.ident, None, True, False,
694 anonymous_node=child_node)
695 compound.fields.append(field)
697 def _create_compound(self, klass, symbol, anonymous):
698 if symbol.ident is None:
699 # the compound is an anonymous member of another union or a struct
701 compound = klass(None, None)
703 compound = self._typedefs_ns.get(symbol.ident, None)
706 # This is a bit of a hack; really we should try
707 # to resolve through the typedefs to find the real
709 if symbol.ident.startswith('_'):
710 compound = self._typedefs_ns.get(symbol.ident[1:], None)
715 name = self.strip_identifier_or_warn(symbol.ident)
718 compound = klass(name, symbol.ident)
720 self._parse_fields(symbol, compound)
721 compound.add_symbol_reference(symbol)
724 def _create_struct(self, symbol, anonymous=False):
725 return self._create_compound(ast.Record, symbol, anonymous)
727 def _create_union(self, symbol, anonymous=False):
728 return self._create_compound(ast.Union, symbol, anonymous)
730 def _create_callback(self, symbol, member=False):
731 parameters = list(self._create_parameters(symbol.base_type.base_type))
732 retval = self._create_return(symbol.base_type.base_type.base_type)
734 # Mark the 'user_data' arguments
735 for i, param in enumerate(parameters):
736 if (param.type.target_fundamental == 'gpointer' and
737 param.argname == 'user_data'):
738 param.closure_name = param.argname
742 elif symbol.ident.find('_') > 0:
743 name = self._strip_symbol_or_warn(symbol)
747 name = self.strip_identifier_or_warn(symbol.ident)
750 callback = ast.Callback(name, retval, parameters, False)
751 callback.add_symbol_reference(symbol)
755 def create_type_from_user_string(self, typestr):
756 """Parse a C type string (as might be given from an
757 annotation) and resolve it. For compatibility, we can consume
758 both GI type string (utf8, Foo.Bar) style, as well as C (char *, FooBar) style."""
760 container = self._create_bare_container_type(typestr)
763 return self._namespace.type_from_name(typestr)
764 typeval = self.create_type_from_ctype_string(typestr)
765 self.resolve_type(typeval)
766 # Explicitly clear out the c_type; there isn't one in this case.
770 def resolve_type(self, typeval):
771 if isinstance(typeval, (ast.Array, ast.List)):
772 self.resolve_type(typeval.element_type)
774 elif isinstance(typeval, ast.Map):
775 self.resolve_type(typeval.key_type)
776 self.resolve_type(typeval.value_type)
778 elif not typeval.resolved and typeval.ctype:
779 pointer_stripped = typeval.ctype.replace('*', '')
781 matches = self.split_ctype_namespaces(pointer_stripped)
782 except ValueError, e:
783 raise TypeResolutionException(e)
785 for namespace, name in matches:
786 target = namespace.get(name)
788 target = namespace.get_by_ctype(pointer_stripped)
790 typeval.target_giname='%s.%s' % (namespace.name, target.name)
793 def _typepair_to_str(self, item):
797 return '%s.%s' % (nsname, item.name)
799 def gtypename_to_giname(self, gtname, names):
800 resolved = names.type_names.get(gtname)
802 return self._typepair_to_str(resolved)
803 resolved = self._names.type_names.get(gtname)
805 return self._typepair_to_str(resolved)
806 raise KeyError("Failed to resolve GType name: %r" % (gtname, ))
808 def ctype_of(self, obj):
809 if hasattr(obj, 'ctype'):
811 elif hasattr(obj, 'symbol'):
816 def follow_aliases(self, type_name, names):
818 resolved = names.aliases.get(type_name)
820 (ns, alias) = resolved
821 type_name = alias.target