#
import ctypes
-import os
from . import cgobject
from .odict import odict
from .ast import (Callback, Enum, Function, Member, Namespace, Parameter,
- Property, Return, Sequence, Struct, Type,
- type_name_from_ctype)
+ Property, Return, Struct, Type, Alias, type_name_from_ctype)
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
GLibInterface, GLibObject, GLibSignal)
-from .utils import resolve_libtool, to_underscores
+from .utils import extract_libtool, to_underscores
class GLibTransformer(object):
def __init__(self, transformer):
self._transformer = transformer
self._namespace_name = None
+ self._aliases = []
self._output_ns = odict()
- self._library = None
- self._type_names = {}
+ self._libraries = []
+ self._internal_types = {}
# Public API
- def load_library(self, libname):
+ def add_library(self, libname):
if libname.endswith('.la'):
- libname = resolve_libtool(libname)
- self._library = ctypes.cdll.LoadLibrary(libname)
+ libname = extract_libtool(libname)
+ self._libraries.append(ctypes.cdll.LoadLibrary(libname))
def parse(self):
namespace = self._transformer.parse()
self._namespace_name = namespace.name
- self._type_names = self._transformer.get_type_names()
+ # First pass, parsing
for node in namespace.nodes:
self._parse_node(node)
- # Second round
+ # Introspection is done from within parsing
+
+ # Second pass, resolving types
for node in self._output_ns.values():
# associate GtkButtonClass with GtkButton
if isinstance(node, Struct):
self._pair_class_struct(node)
+ self._resolve_node(node)
+ # Create a new namespace with what we found
namespace = Namespace(namespace.name)
- namespace.nodes = self._output_ns.values()
+ namespace.nodes = self._aliases + self._output_ns.values()
return namespace
# Private
return self._output_ns.get(name)
def _register_internal_type(self, type_name, node):
- self._type_names[type_name] = (None, node)
+ self._internal_types[type_name] = node
- def _resolve_type_name(self, type_name):
- item = self._type_names.get(type_name)
- if item is not None:
- nsname, item = item
- if nsname is None:
- return item.name
- return '%s.%s' % (nsname, item.name)
- return type_name
+ # Helper functions
- def _resolve_param_type(self, ptype):
- type_name = ptype.name.replace('*', '')
- ptype.name = self._resolve_type_name(type_name)
- return ptype
+ def _create_type(self, type_id):
+ ctype = cgobject.type_name(type_id)
+ type_name = type_name_from_ctype(ctype)
+ return Type(type_name, ctype)
+
+ def _create_gobject(self, node):
+ type_name = 'G' + node.name
+ if type_name == 'GObject':
+ parent_type_name = None
+ symbol = 'intern'
+ else:
+ type_id = cgobject.type_from_name(type_name)
+ parent_type_name = cgobject.type_name(
+ cgobject.type_parent(type_id))
+ symbol = to_underscores(type_name).lower() + '_get_type'
+ node = GLibObject(node.name, parent_type_name, type_name, symbol)
+ type_id = cgobject.TYPE_OBJECT
+ self._introspect_properties(node, type_id)
+ self._introspect_signals(node, type_id)
+ self._add_attribute(node)
+ self._register_internal_type(type_name, node)
+
+ # Parser
def _parse_node(self, node):
if isinstance(node, Enum):
self._parse_struct(node)
elif isinstance(node, Callback):
self._parse_callback(node)
+ elif isinstance(node, Alias):
+ self._parse_alias(node)
elif isinstance(node, Member):
# FIXME: atk_misc_instance singletons
pass
else:
print 'GOBJECT BUILDER: Unhandled node:', node
+ def _parse_alias(self, alias):
+ self._aliases.append(alias)
+
def _parse_enum(self, enum):
self._add_attribute(enum)
elif self._parse_method(func):
return
- self._parse_parameters(func.parameters)
-
self._add_attribute(func)
- def _parse_parameters(self, parameters):
- for parameter in parameters:
- parameter.type = self._resolve_param_type(parameter.type)
-
def _parse_get_type_function(self, func):
- if self._library is None:
+ if not self._libraries:
return False
# GType *_get_type(void)
symbol = func.symbol
if not symbol.endswith('_get_type'):
return False
- if func.retval.type.name != 'GType':
+ if func.retval.type.name != 'GObject.GType':
return False
if func.parameters:
return False
- try:
- func = getattr(self._library, symbol)
- except AttributeError:
+ for library in self._libraries:
+ try:
+ func = getattr(library, symbol)
+ break
+ except AttributeError:
+ continue
+ else:
print 'Warning: could not find symbol: %s' % symbol
return False
class_.methods.append(func)
else:
class_.constructors.append(func)
- self._parse_parameters(func.parameters)
- func.retval.type = self._resolve_param_type(func.retval.type)
return True
def _parse_struct(self, struct):
+ # This is a hack, but GObject is a rather fundamental piece so.
+ if (self._namespace_name == 'GObject' and
+ struct.name in ["Object", 'InitiallyUnowned']):
+ self._create_gobject(struct)
+ return
node = self._output_ns.get(struct.name)
if node is None:
self._add_attribute(struct, replace=True)
for field in class_node.fields[1:]:
node.fields.append(field)
- def _create_type(self, type_id):
- ctype = cgobject.type_name(type_id)
- type_name = type_name_from_ctype(ctype)
- return Type(type_name, ctype)
+ # Introspection
def _introspect_type(self, type_id, symbol):
fundamental_type_id = cgobject.type_fundamental(type_id)
def _introspect_object(self, type_id, symbol):
type_name = cgobject.type_name(type_id)
parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
- node = GLibObject(self._transformer.strip_namespace_object(type_name),
- self._resolve_type_name(parent_type_name),
- type_name, symbol)
+ node = GLibObject(
+ self._transformer.strip_namespace_object(type_name),
+ self._resolve_type_name(parent_type_name),
+ type_name, symbol)
self._introspect_properties(node, type_id)
self._introspect_signals(node, type_id)
self._add_attribute(node)
def _introspect_interface(self, type_id, symbol):
type_name = cgobject.type_name(type_id)
+ parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
node = GLibInterface(
self._transformer.strip_namespace_object(type_name),
+ self._resolve_type_name(parent_type_name),
type_name, symbol)
self._introspect_properties(node, type_id)
self._introspect_signals(node, type_id)
param = Parameter(name, ptype)
signal.parameters.append(param)
node.signals.append(signal)
+
+ # Resolver
+
+ def _resolve_type_name(self, type_name):
+ type_name = type_name.replace('*', '')
+ possible_name = self._transformer.resolve_type_name(type_name)
+ if possible_name != type_name:
+ return possible_name
+ possible_node = self._internal_types.get(type_name)
+ if possible_node:
+ return possible_node.name
+ return type_name
+
+ def _resolve_param_type(self, ptype):
+ ptype.name = ptype.name.replace('*', '')
+ type_name = ptype.name
+ type_name = self._transformer.resolve_possible_typedef(type_name)
+ possible_node = self._internal_types.get(type_name)
+ if possible_node:
+ ptype.name = possible_node.name
+ else:
+ ptype = self._transformer.resolve_param_type(ptype)
+ return ptype
+
+ def _resolve_node(self, node):
+ if isinstance(node, (Callback, Function)):
+ self._resolve_function(node)
+ elif isinstance(node, GLibObject):
+ self._resolve_glib_object(node)
+ elif isinstance(node, GLibInterface):
+ self._resolve_glib_interface(node)
+ elif isinstance(node, GLibBoxed):
+ self._resolve_glib_boxed(node)
+ elif isinstance(node, Struct):
+ self._resolve_struct(node)
+
+ def _resolve_struct(self, node):
+ for field in node.fields:
+ self._resolve_field(field)
+
+ def _resolve_glib_interface(self, node):
+ self._resolve_methods(node.methods)
+ self._resolve_properties(node.properties)
+ self._resolve_signals(node.signals)
+
+ def _resolve_glib_object(self, node):
+ self._resolve_constructors(node.constructors)
+ self._resolve_methods(node.methods)
+ self._resolve_properties(node.properties)
+ self._resolve_signals(node.signals)
+
+ def _resolve_glib_boxed(self, node):
+ self._resolve_constructors(node.constructors)
+ self._resolve_methods(node.methods)
+
+ def _resolve_constructors(self, constructors):
+ for ctor in constructors:
+ self._resolve_function(ctor)
+
+ def _resolve_methods(self, methods):
+ for method in methods:
+ self._resolve_function(method)
+
+ def _resolve_signals(self, signals):
+ for signal in signals:
+ self._resolve_function(signal)
+
+ def _resolve_properties(self, properties):
+ for prop in properties:
+ self._resolve_property(prop)
+
+ def _resolve_property(self, prop):
+ prop.type = self._resolve_param_type(prop.type)
+
+ def _resolve_function(self, func):
+ self._resolve_parameters(func.parameters)
+ func.retval.type = self._resolve_param_type(func.retval.type)
+
+ def _resolve_parameters(self, parameters):
+ for parameter in parameters:
+ parameter.type = self._resolve_param_type(parameter.type)
+
+ def _resolve_field(self, field):
+ if isinstance(field, Callback):
+ self._resolve_function(field)
+ return
+ field.type = self._resolve_param_type(field.type)