summaryrefslogtreecommitdiff
path: root/giscanner
diff options
context:
space:
mode:
authorColin Walters <walters@src.gnome.org>2008-11-13 19:57:12 +0000
committerColin Walters <walters@src.gnome.org>2008-11-13 19:57:12 +0000
commitb76cca0eb5ea3363ef738b7c9b3d3e9eefea6b79 (patch)
treed11bbc4e4fcf7fbf927a2ac801f793dfcc9bbfed /giscanner
parentb1b589ab793633352be375e18f0b3a821ae70afe (diff)
downloadgobject-introspection-b76cca0eb5ea3363ef738b7c9b3d3e9eefea6b79.tar.gz
Bug 558436 - avoid having scanner load app code
svn path=/trunk/; revision=912
Diffstat (limited to 'giscanner')
-rw-r--r--giscanner/Makefile.am2
-rw-r--r--giscanner/cgobject.py303
-rw-r--r--giscanner/glibtransformer.py335
-rw-r--r--giscanner/transformer.py19
4 files changed, 164 insertions, 495 deletions
diff --git a/giscanner/Makefile.am b/giscanner/Makefile.am
index c9d23e58..1d6942b4 100644
--- a/giscanner/Makefile.am
+++ b/giscanner/Makefile.am
@@ -37,8 +37,8 @@ pkgpyexec_PYTHON = \
__init__.py \
ast.py \
cachestore.py \
- cgobject.py \
config.py \
+ dumper.py \
girparser.py \
girwriter.py \
glibast.py \
diff --git a/giscanner/cgobject.py b/giscanner/cgobject.py
deleted file mode 100644
index 308ebf49..00000000
--- a/giscanner/cgobject.py
+++ /dev/null
@@ -1,303 +0,0 @@
-# -*- Mode: Python -*-
-# GObject-Introspection - a framework for introspecting GObject libraries
-# Copyright (C) 2008 Johan Dahlin
-#
-# This library is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2 of the License, or (at your option) any later version.
-#
-# This library is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this library; if not, write to the
-# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-# Boston, MA 02111-1307, USA.
-#
-
-# Poor mans GObject python bindings
-# Incidentally portable beyond CPython, due to usage of ctypes
-# Why not PyGObject?
-# - 1) Avoid PyGObject dependency
-# - 2) Low-level binding
-# - 3) Implementation independent
-# - 4) Usage lower in the stack
-#
-# based on defsgen.py (C) 2006 John Finlay
-#
-
-import os
-import ctypes
-from ctypes.util import find_library
-
-
-# Constants
-
-# from gobject/gtype.h
-
-
-def _make_fundamental(x):
- G_TYPE_FUNDAMENTAL_SHIFT = 2
- return x << G_TYPE_FUNDAMENTAL_SHIFT
-
-
-TYPE_INVALID = _make_fundamental(0)
-TYPE_NONE = _make_fundamental(1)
-TYPE_INTERFACE = _make_fundamental(2)
-TYPE_CHAR = _make_fundamental(3)
-TYPE_UCHAR = _make_fundamental(4)
-TYPE_BOOLEAN = _make_fundamental(5)
-TYPE_INT = _make_fundamental(6)
-TYPE_UINT = _make_fundamental(7)
-TYPE_LONG = _make_fundamental(8)
-TYPE_ULONG = _make_fundamental(9)
-TYPE_INT64 = _make_fundamental(10)
-TYPE_UINT64 = _make_fundamental(11)
-TYPE_ENUM = _make_fundamental(12)
-TYPE_FLAGS = _make_fundamental(13)
-TYPE_FLOAT = _make_fundamental(14)
-TYPE_DOUBLE = _make_fundamental(15)
-TYPE_STRING = _make_fundamental(16)
-TYPE_POINTER = _make_fundamental(17)
-TYPE_BOXED = _make_fundamental(18)
-TYPE_PARAM = _make_fundamental(19)
-TYPE_OBJECT = _make_fundamental(20)
-
-# Typedefs
-
-# FIXME - this is wrong on win64, where long == 32 but size_t == 64
-GType = ctypes.c_ulong
-
-TYPE_FLAG_ABSTRACT = 1 << 4
-
-# Structs
-
-
-class GTypeClass(ctypes.Structure):
- _fields_ = [('g_type', GType)]
-
-
-class GTypeInstance(ctypes.Structure):
- _fields_ = [('g_class', ctypes.POINTER(GTypeClass))]
-
-
-class GEnumValue(ctypes.Structure):
- _fields_ = [('value', ctypes.c_int),
- ('value_name', ctypes.c_char_p),
- ('value_nick', ctypes.c_char_p)]
-
-
-class GFlagsValue(ctypes.Structure):
- _fields_ = [('value', ctypes.c_uint),
- ('value_name', ctypes.c_char_p),
- ('value_nick', ctypes.c_char_p)]
-
-
-class GEnumClass(ctypes.Structure):
- _fields_ = [('g_type_class', GTypeClass),
- ('minimum', ctypes.c_int),
- ('maximum', ctypes.c_int),
- ('n_values', ctypes.c_uint),
- ('values', ctypes.POINTER(GEnumValue))]
-
- def get_values(self):
- for i in range(self.n_values):
- yield self.values[i]
-
-
-class GFlagsClass(ctypes.Structure):
- _fields_ = [('g_type_class', GTypeClass),
- ('mask', ctypes.c_uint),
- ('n_values', ctypes.c_uint),
- ('values', ctypes.POINTER(GFlagsValue))]
-
- def get_values(self):
- for i in range(self.n_values):
- yield self.values[i]
-
-
-class GTypeInterface(ctypes.Structure):
- _fields_ = [('g_type', GType),
- ('g_instance_type', GType)]
-
-
-class GParamSpec(ctypes.Structure):
- _fields_ = [('g_type_instance', GTypeInstance),
- ('name', ctypes.c_char_p),
- ('flags', ctypes.c_uint),
- ('value_type', GType),
- ('owner_type', GType)]
-
-
-class GSignalInfo(ctypes.Structure):
- _fields_ = [('signal_id', ctypes.c_uint),
- ('signal_name', ctypes.c_char_p),
- ('itype', GType),
- ('signal_flags', ctypes.c_uint),
- ('return_type', GType),
- ('n_params', ctypes.c_uint),
- ('param_types', ctypes.POINTER(GType))]
-
- def get_params(self):
- for i in range(self.n_params):
- yield self.param_types[i]
-
-
-if os.name == 'nt':
- _library_path = find_library('libgobject-2.0-0')
-else:
- _library_path = find_library('gobject-2.0')
-if not _library_path:
- raise ImportError("Could not find gobject-2.0 library")
-_gobj = ctypes.CDLL(_library_path, ctypes.RTLD_GLOBAL)
-_gobj.g_type_init()
-
-# We need to initialize threads just in case part of the library
-# wants to use gthreads; libsoup seems to use g_once for its
-# type init functions.
-if os.name == 'nt':
- _threads_library_path = find_library('libgthread-2.0-0')
-else:
- _threads_library_path = find_library('gthread-2.0')
-if not _threads_library_path:
- raise ImportError("Could not find gthread-2.0 library")
-_gthreads = ctypes.CDLL(_threads_library_path, ctypes.RTLD_GLOBAL)
-_gthreads.g_thread_init.argtypes = [ctypes.c_void_p]
-_gthreads.g_thread_init(None)
-
-# Functions
-
-
-def _gwrap(fname, ret, *argtypes):
-
- def _deco(f):
- f._cfunc = getattr(_gobj, fname)
- f._cfunc.restype = ret
- f._cfunc.argtypes = argtypes
- return f
- return _deco
-
-
-@_gwrap('g_object_new', ctypes.c_void_p, GType)
-def object_new(type_id):
- return _gobj.g_object_new(type_id, None)
-
-
-# Workaround this error:
-# GLib-GObject-CRITICAL **: g_param_spec_pool_list:
-# assertion `pool != NULL' failed
-# which happens when trying to introspect an interface before instantiating
-# a GObject.
-
-object_new(TYPE_OBJECT)
-_gobj.g_initially_unowned_get_type()
-
-
-@_gwrap('g_type_name', ctypes.c_char_p, GType)
-def type_name(type_id):
- return _gobj.g_type_name(type_id)
-
-
-@_gwrap('g_type_from_name', GType, ctypes.c_char_p)
-def type_from_name(name):
- return _gobj.g_type_from_name(name)
-
-
-@_gwrap('g_type_fundamental', GType, GType)
-def type_fundamental(type_id):
- return _gobj.g_type_fundamental(type_id)
-
-
-@_gwrap('g_type_test_flags', ctypes.c_int, GType, ctypes.c_int)
-def type_test_flags(type_id, flag):
- return _gobj.g_type_test_flags(type_id, flag)
-
-
-def type_is_abstract(type_id):
- return type_test_flags(type_id, TYPE_FLAG_ABSTRACT) != 0
-
-
-@_gwrap('g_type_parent', GType, GType)
-def type_parent(type_id):
- return _gobj.g_type_parent(type_id)
-
-
-@_gwrap('g_type_class_ref', ctypes.POINTER(GTypeClass), GType)
-def type_class_ref(type_id):
- fundamental_type = type_fundamental(type_id)
- if fundamental_type == TYPE_INVALID:
- return None
- if fundamental_type == TYPE_ENUM:
- typeclass = GEnumClass
- elif fundamental_type == TYPE_FLAGS:
- typeclass = GFlagsClass
- else:
- raise NotImplementedError(fundamental_type)
- ptr = _gobj.g_type_class_ref(type_id)
- return ctypes.cast(ptr, ctypes.POINTER(typeclass)).contents
-
-
-@_gwrap('g_object_class_list_properties',
- ctypes.POINTER(ctypes.POINTER(GParamSpec)),
- ctypes.POINTER(GTypeClass), ctypes.POINTER(ctypes.c_uint))
-def object_class_list_properties(type_id):
- klass = _gobj.g_type_class_ref(type_id)
- n = ctypes.c_uint()
- pspecs = _gobj.g_object_class_list_properties(klass, ctypes.byref(n))
- for i in range(n.value):
- yield ctypes.cast(pspecs[i], ctypes.POINTER(GParamSpec)).contents
-
-
-@_gwrap('g_type_default_interface_ref', ctypes.c_void_p, GType)
-def type_default_interface_ref(type_id):
- return _gobj.g_type_default_interface_ref(type_id)
-
-
-@_gwrap('g_object_interface_list_properties',
- ctypes.POINTER(ctypes.POINTER(GParamSpec)),
- ctypes.c_void_p, ctypes.POINTER(ctypes.c_uint))
-def object_interface_list_properties(type_id):
- iface = type_default_interface_ref(type_id)
- n = ctypes.c_uint()
- pspecs = _gobj.g_object_interface_list_properties(iface, ctypes.byref(n))
- for i in range(n.value):
- yield ctypes.cast(pspecs[i], ctypes.POINTER(GParamSpec)).contents
-
-
-@_gwrap('g_type_interfaces', ctypes.POINTER(GType), GType,
- ctypes.POINTER(ctypes.c_uint))
-def type_interfaces(type_id):
- n = ctypes.c_uint()
- type_ids = _gobj.g_type_interfaces(type_id, ctypes.byref(n))
- for i in range(n.value):
- yield type_ids[i]
-
-
-@_gwrap('g_type_interface_prerequisites', ctypes.POINTER(GType), GType,
- ctypes.POINTER(ctypes.c_uint))
-def type_interface_prerequisites(type_id):
- n = ctypes.c_uint()
- type_ids = _gobj.g_type_interface_prerequisites(type_id, ctypes.byref(n))
- for i in range(n.value):
- yield type_ids[i]
-
-
-@_gwrap('g_signal_query', None, ctypes.c_uint, ctypes.POINTER(GSignalInfo))
-def signal_query(sigid, qptr):
- _gobj.g_signal_query(sigid, qptr)
-
-
-@_gwrap('g_signal_list_ids', ctypes.POINTER(ctypes.c_uint),
- GType, ctypes.POINTER(ctypes.c_uint))
-def signal_list(type_id):
- n = ctypes.c_uint()
- signal_ids = _gobj.g_signal_list_ids(type_id, ctypes.byref(n))
- for i in range(n.value):
- info = GSignalInfo()
- signal_query(signal_ids[i], ctypes.byref(info))
- yield info
-
-TYPE_GTYPE = type_from_name('GType')
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index f97af9fa..a414078e 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -19,11 +19,12 @@
#
import os
+import sys
import re
-import ctypes
-from ctypes.util import find_library
+import tempfile
+import shutil
+import subprocess
-from . import cgobject
from .ast import (Callback, Constant, Enum, Function, Member, Namespace,
Parameter, Property, Return, Struct, Type, Alias,
Union, Field, type_name_from_ctype,
@@ -32,10 +33,20 @@ from .transformer import Names
from .glibast import (GLibBoxed, GLibEnum, GLibEnumMember, GLibFlags,
GLibInterface, GLibObject, GLibSignal, GLibBoxedStruct,
GLibBoxedUnion, GLibBoxedOther, type_names)
-from .utils import extract_libtool, to_underscores, to_underscores_noprefix
+from .utils import to_underscores, to_underscores_noprefix
default_array_types['guchar*'] = TYPE_UINT8
+# GParamFlags
+G_PARAM_READABLE = 1 << 0
+G_PARAM_WRITABLE = 1 << 1
+G_PARAM_CONSTRUCT = 1 << 2
+G_PARAM_CONSTRUCT_ONLY = 1 << 3
+G_PARAM_LAX_VALIDATION = 1 << 4
+G_PARAM_STATIC_NAME = 1 << 5
+G_PARAM_STATIC_NICK = 1 << 6
+G_PARAM_STATIC_BLURB = 1 << 7
+
SYMBOL_BLACKLIST = [
# These ones break GError conventions
'g_simple_async_result_new_from_error',
@@ -49,6 +60,16 @@ SYMBOL_BLACKLIST_RE = [re.compile(x) for x in \
[r'\w+_marshal_[A-Z]+__', ]]
+class IntrospectionBinary(object):
+
+ def __init__(self, args, tmpdir=None):
+ self.args = args
+ if tmpdir is None:
+ self.tmpdir = tempfile.mkdtemp('', 'tmp-introspect')
+ else:
+ self.tmpdir = tmpdir
+
+
class Unresolved(object):
def __init__(self, target):
@@ -68,7 +89,9 @@ class GLibTransformer(object):
self._namespace_name = None
self._names = Names()
self._uscore_type_names = {}
- self._libraries = []
+ self._binary = None
+ self._get_type_functions = []
+ self._gtype_data = {}
self._failed_types = {}
self._boxed_types = {}
self._private_internal_types = {}
@@ -77,23 +100,8 @@ class GLibTransformer(object):
# Public API
- def add_library(self, libname):
- # For testing mainly.
- libtool_libname = 'lib' + libname + '.la'
- if os.path.exists(libname):
- found_libname = os.path.abspath(libname)
- elif os.path.exists(libtool_libname):
- found_libname = extract_libtool(libtool_libname)
- else:
- found_libname = find_library(libname)
-
- if libname.endswith('.la'):
- found_libname = extract_libtool(libname)
- libname = os.path.basename(found_libname)
- if not found_libname:
- raise ValueError("Failed to find library: %r" % (libname, ))
- self._libraries.append(ctypes.cdll.LoadLibrary(found_libname))
- return libname
+ def set_introspection_binary(self, binary):
+ self._binary = binary
def _print_statistics(self):
nodes = list(self._names.names.itervalues())
@@ -120,6 +128,11 @@ class GLibTransformer(object):
if namespace.name == 'GObject':
del self._names.aliases['Type']
+ # Get all the GObject data by passing our list of get_type
+ # functions to the compiled binary
+
+ self._execute_binary()
+
# Introspection is done from within parsing
# Second pass: pair boxed structures
@@ -169,6 +182,16 @@ class GLibTransformer(object):
return node[1]
return None
+ def _lookup_node(self, name):
+ if name in type_names:
+ return None
+ node = self._get_attribute(name)
+ if node is None:
+ node = self._transformer.get_names().names.get(name)
+ if node:
+ return node[1]
+ return node
+
def _register_internal_type(self, type_name, node):
self._names.type_names[type_name] = (None, node)
uscored = to_underscores(type_name).lower()
@@ -183,16 +206,6 @@ class GLibTransformer(object):
# Helper functions
- def _type_from_gtype(self, type_id):
- ctype = cgobject.type_name(type_id)
- type_name = type_name_from_ctype(ctype)
- type_name = type_name.replace('*', '')
- type_name = self._resolve_type_name(type_name)
-
- type = Type(type_name, ctype)
- type._gtype = type_id
- return type
-
def _resolve_gtypename(self, gtype_name):
try:
return self._transformer.gtypename_to_giname(gtype_name,
@@ -200,21 +213,45 @@ class GLibTransformer(object):
except KeyError, e:
return Unresolved(gtype_name)
+ def _execute_binary(self):
+ in_path = os.path.join(self._binary.tmpdir, 'types.txt')
+ f = open(in_path, 'w')
+ for func in self._get_type_functions:
+ f.write(func)
+ f.write('\n')
+ f.close()
+ out_path = os.path.join(self._binary.tmpdir, 'dump.xml')
+
+ introspect_arg = '--introspect-dump=%s,%s' % (in_path, out_path)
+ args = self._binary.args
+ args.append(introspect_arg)
+ # Invoke the binary, having written our get_type functions to types.txt
+ print args
+ subprocess.check_call(args, stdout=sys.stdout, stderr=sys.stderr)
+ self._read_introspect_dump(out_path)
+
+ # Clean up temporaries
+ shutil.rmtree(self._binary.tmpdir)
+
+ def _read_introspect_dump(self, xmlpath):
+ from xml.etree.cElementTree import parse
+ tree = parse(xmlpath)
+ root = tree.getroot()
+ for child in root:
+ self._gtype_data[child.attrib['name']] = child
+ for child in root:
+ self._introspect_type(child)
+
def _create_gobject(self, node):
type_name = 'G' + node.name
if type_name == 'GObject':
parent_gitype = None
symbol = 'intern'
- else:
- type_id = cgobject.type_from_name(type_name)
- parent_type_name = cgobject.type_name(
- cgobject.type_parent(type_id))
+ elif type_name == 'GInitiallyUnowned':
+ parent_type_name = 'GObject'
parent_gitype = self._resolve_gtypename(parent_type_name)
- symbol = to_underscores(type_name).lower() + '_get_type'
+ symbol = 'g_initially_unowned_get_type'
node = GLibObject(node.name, parent_gitype, type_name, symbol, True)
- 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)
@@ -281,26 +318,7 @@ class GLibTransformer(object):
", not GObject.Type") % (func.retval.type.name, )
return False
- if not self._libraries:
- print "Warning: No libraries loaded, cannot call %s" % (symbol, )
- return False
-
- for library in self._libraries:
- try:
- func = getattr(library, symbol)
- break
- except AttributeError:
- continue
- else:
- print 'Warning: could not find symbol: %s' % symbol
- name = symbol.replace('_get_type', '')
- self._failed_types[name] = True
- return False
-
- func.restype = cgobject.GType
- func.argtypes = []
- type_id = func()
- self._introspect_type(type_id, symbol)
+ self._get_type_functions.append(symbol)
return True
def _name_is_internal_gtype(self, giname):
@@ -491,65 +509,51 @@ class GLibTransformer(object):
# Introspection
- def _introspect_type(self, type_id, symbol):
- fundamental_type_id = cgobject.type_fundamental(type_id)
- if (fundamental_type_id == cgobject.TYPE_ENUM or
- fundamental_type_id == cgobject.TYPE_FLAGS):
- self._introspect_enum(fundamental_type_id, type_id, symbol)
- elif fundamental_type_id == cgobject.TYPE_OBJECT:
- self._introspect_object(type_id, symbol)
- elif fundamental_type_id == cgobject.TYPE_INTERFACE:
- self._introspect_interface(type_id, symbol)
- elif fundamental_type_id == cgobject.TYPE_BOXED:
- self._introspect_boxed(type_id, symbol)
- elif fundamental_type_id == cgobject.TYPE_BOXED:
- self._introspect_boxed(type_id, symbol)
- elif fundamental_type_id == cgobject.TYPE_POINTER:
- # FIXME: Should we do something about these?
- # GHashTable, GValue and a few other fundamentals are
- # covered here
- return
+ def _introspect_type(self, xmlnode):
+ if xmlnode.tag in ('enum', 'flags'):
+ self._introspect_enum(xmlnode)
+ elif xmlnode.tag == 'class':
+ self._introspect_object(xmlnode)
+ elif xmlnode.tag == 'interface':
+ self._introspect_interface(xmlnode)
+ elif xmlnode.tag == 'boxed':
+ self._introspect_boxed(xmlnode)
else:
- print 'unhandled GType: %s(%d)' % (cgobject.type_name(type_id),
- type_id)
-
- def _introspect_enum(self, ftype_id, type_id, symbol):
- type_class = cgobject.type_class_ref(type_id)
- if type_class is None:
- return
+ raise ValueError("Unhandled introspection XML tag %s", xmlnode.tag)
+ def _introspect_enum(self, node):
members = []
- for enum_value in type_class.get_values():
- members.append(GLibEnumMember(enum_value.value_nick,
- enum_value.value,
- enum_value.value_name,
- enum_value.value_nick))
-
- klass = (GLibFlags if ftype_id == cgobject.TYPE_FLAGS else GLibEnum)
- type_name = cgobject.type_name(type_id)
+ for member in node.findall('member'):
+ members.append(GLibEnumMember(member.attrib['nick'],
+ member.attrib['value'],
+ member.attrib['name'],
+ member.attrib['nick']))
+
+ klass = (GLibFlags if node.tag == 'flags' else GLibEnum)
+ type_name = node.attrib['name']
enum_name = self._transformer.remove_prefix(type_name)
- node = klass(enum_name, type_name, members, symbol)
+ node = klass(enum_name, type_name, members, node.attrib['get-type'])
self._add_attribute(node, replace=True)
self._register_internal_type(type_name, node)
- def _introspect_object(self, type_id, symbol):
- type_name = cgobject.type_name(type_id)
+ def _introspect_object(self, xmlnode):
+ type_name = xmlnode.attrib['name']
# We handle this specially above; in 2.16 and below there
# was no g_object_get_type, for later versions we need
# to skip it
if type_name == 'GObject':
return
- parent_type_name = cgobject.type_name(cgobject.type_parent(type_id))
+ parent_type_name = xmlnode.attrib['parent']
parent_gitype = self._resolve_gtypename(parent_type_name)
- is_abstract = cgobject.type_is_abstract(type_id)
+ is_abstract = not not xmlnode.attrib.get('abstract', False)
node = GLibObject(
self._transformer.remove_prefix(type_name),
parent_gitype,
type_name,
- symbol, is_abstract)
- self._introspect_properties(node, type_id)
- self._introspect_signals(node, type_id)
- self._introspect_implemented_interfaces(node, type_id)
+ xmlnode.attrib['get-type'], is_abstract)
+ self._introspect_properties(node, xmlnode)
+ self._introspect_signals(node, xmlnode)
+ self._introspect_implemented_interfaces(node, xmlnode)
# add struct fields
struct = self._get_attribute(node.name)
@@ -564,84 +568,69 @@ class GLibTransformer(object):
self._add_attribute(node, replace=True)
self._register_internal_type(type_name, 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))
- if parent_type_name == 'GInterface':
- parent_gitype = None
- else:
- parent_gitype = self._resolve_gtypename(parent_type_name)
+ def _introspect_interface(self, xmlnode):
+ type_name = xmlnode.attrib['name']
node = GLibInterface(
self._transformer.remove_prefix(type_name),
- parent_gitype,
- type_name, symbol)
- self._introspect_properties(node, type_id)
- self._introspect_signals(node, type_id)
+ None,
+ type_name, xmlnode.attrib['get-type'])
+ self._introspect_properties(node, xmlnode)
+ self._introspect_signals(node, xmlnode)
# GtkFileChooserEmbed is an example of a private interface, we
# just filter them out
- if symbol.startswith('_'):
+ if xmlnode.attrib['get-type'].startswith('_'):
print "NOTICE: Marking %s as internal type" % (type_name, )
self._private_internal_types[type_name] = node
else:
self._add_attribute(node, replace=True)
self._register_internal_type(type_name, node)
- def _introspect_boxed(self, type_id, symbol):
- type_name = cgobject.type_name(type_id)
+ def _introspect_boxed(self, xmlnode):
+ type_name = xmlnode.attrib['name']
# This one doesn't go in the main namespace; we associate it with
# the struct or union
- node = GLibBoxed(type_name, symbol)
+ node = GLibBoxed(type_name, xmlnode.attrib['get-type'])
self._boxed_types[node.type_name] = node
self._register_internal_type(type_name, node)
- def _introspect_implemented_interfaces(self, node, type_id):
- fundamental_type_id = cgobject.type_fundamental(type_id)
- if fundamental_type_id != cgobject.TYPE_OBJECT:
- raise AssertionError
- interfaces = cgobject.type_interfaces(type_id)
+ def _introspect_implemented_interfaces(self, node, xmlnode):
gt_interfaces = []
- for interface_typeid in interfaces:
- iname = cgobject.type_name(interface_typeid)
- gitype = self._resolve_gtypename(iname)
+ for interface in xmlnode.findall('implements'):
+ gitype = self._resolve_gtypename(interface.attrib['name'])
gt_interfaces.append(gitype)
node.interfaces = gt_interfaces
- def _introspect_properties(self, node, type_id):
- fundamental_type_id = cgobject.type_fundamental(type_id)
- if fundamental_type_id == cgobject.TYPE_OBJECT:
- pspecs = cgobject.object_class_list_properties(type_id)
- elif fundamental_type_id == cgobject.TYPE_INTERFACE:
- pspecs = cgobject.object_interface_list_properties(type_id)
- else:
- raise AssertionError
-
- for pspec in pspecs:
- if pspec.owner_type != type_id:
- continue
- ctype = cgobject.type_name(pspec.value_type)
- readable = (pspec.flags & 1) != 0
- writable = (pspec.flags & 2) != 0
- construct = (pspec.flags & 4) != 0
- construct_only = (pspec.flags & 8) != 0
+ def _introspect_properties(self, node, xmlnode):
+ for pspec in xmlnode.findall('property'):
+ ctype = pspec.attrib['type']
+ flags = int(pspec.attrib['flags'])
+ readable = (flags & G_PARAM_READABLE) != 0
+ writable = (flags & G_PARAM_WRITABLE) != 0
+ construct = (flags & G_PARAM_CONSTRUCT) != 0
+ construct_only = (flags & G_PARAM_CONSTRUCT_ONLY) != 0
node.properties.append(Property(
- pspec.name,
+ pspec.attrib['name'],
type_name_from_ctype(ctype),
readable, writable, construct, construct_only,
ctype,
))
- def _introspect_signals(self, node, type_id):
- for signal_info in cgobject.signal_list(type_id):
- rtype = self._type_from_gtype(signal_info.return_type)
- return_ = Return(rtype)
- signal = GLibSignal(signal_info.signal_name, return_)
- for i, parameter in enumerate(signal_info.get_params()):
+ def _introspect_signals(self, node, xmlnode):
+ for signal_info in xmlnode.findall('signal'):
+ rctype = signal_info.attrib['return']
+ rtype = Type(self._transformer.parse_ctype(rctype), rctype)
+ return_ = Return(rtype, signal_info.attrib['return'])
+ return_.transfer = 'full'
+ signal = GLibSignal(signal_info.attrib['name'], return_)
+ for i, parameter in enumerate(signal_info.findall('param')):
if i == 0:
name = 'object'
else:
name = 'p%s' % (i-1, )
- ptype = self._type_from_gtype(parameter)
+ pctype = parameter.attrib['type']
+ ptype = Type(self._transformer.parse_ctype(pctype), pctype)
param = Parameter(name, ptype)
+ param.transfer = 'none'
signal.parameters.append(param)
node.signals.append(signal)
@@ -651,7 +640,6 @@ class GLibTransformer(object):
# Workaround glib bug #548689, to be included in 2.18.0
if type_name == "GParam":
type_name = "GObject.ParamSpec"
-
res = self._transformer.resolve_type_name_full
try:
return res(type_name, ctype, self._names)
@@ -659,6 +647,9 @@ class GLibTransformer(object):
return self._transformer.resolve_type_name(type_name, ctype)
def _resolve_param_type(self, ptype, **kwargs):
+ # Workaround glib bug #548689, to be included in 2.18.0
+ if ptype.name == "GParam":
+ ptype.name = "GObject.ParamSpec"
return self._transformer.resolve_param_type_full(ptype,
self._names,
**kwargs)
@@ -783,43 +774,23 @@ class GLibTransformer(object):
prop.type = self._resolve_param_type(prop.type, allow_invalid=False)
def _adjust_transfer(self, param):
- # Do GLib/GObject-specific type transformations here
-
- transfer = None
- is_object = None
- if hasattr(param.type, '_gtype'):
- ftype = cgobject.type_fundamental(param.type._gtype)
- assert ftype != cgobject.TYPE_INVALID, param.type._gtype
+ if not (param.transfer is None or param.transfer_inferred):
+ return
- is_object = ftype in [cgobject.TYPE_OBJECT,
- cgobject.TYPE_INTERFACE]
+ # Do GLib/GObject-specific type transformations here
+ node = self._lookup_node(param.type.name)
+ if node is None:
+ return
- if ftype in [cgobject.TYPE_OBJECT,
- cgobject.TYPE_INTERFACE,
- cgobject.TYPE_STRING,
- cgobject.TYPE_BOXED,
- cgobject.TYPE_PARAM]:
+ if isinstance(param, Parameter):
+ if param.direction != PARAM_DIRECTION_IN:
transfer = 'full'
else:
- # if type is a cgobject.TYPE_POINTER we could require direction
- # and transfer-ownership annotations
transfer = 'none'
-
- if is_object is None:
- is_object = (param.type.name == 'GObject.Object' or
- (self._namespace_name == 'GObject' and
- param.type.name == 'Object'))
-
- # Default to full transfer for GObjects
- if isinstance(param, Parameter):
- is_out = (param.direction != PARAM_DIRECTION_IN)
else:
- is_out = True
- if param.transfer is None or param.transfer_inferred:
- if is_out and is_object:
- param.transfer = 'full'
- elif transfer is not None:
- param.transfer = transfer
+ transfer = 'full'
+
+ param.transfer = transfer
def _adjust_throws(self, func):
if func.parameters == []:
diff --git a/giscanner/transformer.py b/giscanner/transformer.py
index c512f7a4..fbf82ffd 100644
--- a/giscanner/transformer.py
+++ b/giscanner/transformer.py
@@ -142,7 +142,8 @@ class Transformer(object):
self._names.aliases[node.name] = (nsname, node)
elif isinstance(node, (GLibBoxed, Interface, Class)):
self._names.type_names[node.type_name] = (nsname, node)
- self._names.names[node.name] = (nsname, node)
+ giname = '%s.%s' % (nsname, node.name)
+ self._names.names[giname] = (nsname, node)
if hasattr(node, 'ctype'):
self._names.ctypes[node.ctype] = (nsname, node)
elif hasattr(node, 'symbol'):
@@ -370,7 +371,7 @@ class Transformer(object):
"symbol %r of type %s" % (symbol.ident, ctype_name(ctype)))
return node
- def _parse_ctype(self, ctype):
+ def parse_ctype(self, ctype):
# First look up the ctype including any pointers;
# a few type names like 'char*' have their own aliases
# and we need pointer information for those.
@@ -398,29 +399,29 @@ class Transformer(object):
if ctype in self._list_ctypes:
param = options.get('element-type')
if param:
- contained_type = self._parse_ctype(param[0])
+ contained_type = self.parse_ctype(param[0])
else:
contained_type = None
- derefed_name = self._parse_ctype(ctype)
+ derefed_name = self.parse_ctype(ctype)
rettype = List(derefed_name,
ctype,
contained_type)
elif ctype in self._map_ctypes:
param = options.get('element-type')
if param:
- key_type = self._parse_ctype(param[0])
- value_type = self._parse_ctype(param[1])
+ key_type = self.parse_ctype(param[0])
+ value_type = self.parse_ctype(param[1])
else:
key_type = None
value_type = None
- derefed_name = self._parse_ctype(ctype)
+ derefed_name = self.parse_ctype(ctype)
rettype = Map(derefed_name,
ctype,
key_type, value_type)
elif (ctype in default_array_types) or ('array' in options):
derefed_name = ctype[:-1] if ctype[-1] == '*' else ctype
rettype = Array(ctype,
- self._parse_ctype(derefed_name))
+ self.parse_ctype(derefed_name))
array_opts = dict([opt.split('=')
for opt in options.get('array', [])])
if 'length' in array_opts:
@@ -429,7 +430,7 @@ class Transformer(object):
rettype.size = array_opts['fixed-size']
rettype.zeroterminated = False
else:
- derefed_name = self._parse_ctype(ctype)
+ derefed_name = self.parse_ctype(ctype)
rettype = Type(derefed_name, ctype)
# Deduce direction for some types passed by reference that