From b24fd9633cabe1d95cde173a04e9a49833b06a26 Mon Sep 17 00:00:00 2001 From: Simon van der Linden Date: Sun, 8 Nov 2009 12:35:08 +0100 Subject: Initial import --- .gitignore | 33 + Makefile.am | 10 + autogen.sh | 159 +++ configure.ac | 53 + gi/Makefile.am | 50 + gi/__init__.py | 24 + gi/gimodule.c | 144 ++ gi/importer.py | 89 ++ gi/module.py | 167 +++ gi/overrides/Gdk.py | 21 + gi/overrides/Gtk.py | 13 + gi/overrides/Makefile.am | 10 + gi/overrides/__init__.py | 0 gi/pygi-argument.c | 1976 ++++++++++++++++++++++++++ gi/pygi-argument.h | 65 + gi/pygi-info.c | 2093 ++++++++++++++++++++++++++++ gi/pygi-info.h | 64 + gi/pygi-private.h | 55 + gi/pygi-repository.c | 238 ++++ gi/pygi-repository.h | 39 + gi/pygi-struct.c | 175 +++ gi/pygi-struct.h | 40 + gi/pygi-type.c | 96 ++ gi/pygi-type.h | 43 + gi/pygi.h | 99 ++ gi/pygobject-external.h | 83 ++ gi/repository/Makefile.am | 8 + gi/repository/__init__.py | 30 + gi/types.py | 163 +++ tests/Makefile.am | 48 + tests/libtestgi.c | 3397 +++++++++++++++++++++++++++++++++++++++++++++ tests/libtestgi.h | 643 +++++++++ tests/runtests.py | 22 + tests/test_gi.py | 1416 +++++++++++++++++++ 34 files changed, 11566 insertions(+) create mode 100644 .gitignore create mode 100644 Makefile.am create mode 100755 autogen.sh create mode 100644 configure.ac create mode 100644 gi/Makefile.am create mode 100644 gi/__init__.py create mode 100644 gi/gimodule.c create mode 100644 gi/importer.py create mode 100644 gi/module.py create mode 100644 gi/overrides/Gdk.py create mode 100644 gi/overrides/Gtk.py create mode 100644 gi/overrides/Makefile.am create mode 100644 gi/overrides/__init__.py create mode 100644 gi/pygi-argument.c create mode 100644 gi/pygi-argument.h create mode 100644 gi/pygi-info.c create mode 100644 gi/pygi-info.h create mode 100644 gi/pygi-private.h create mode 100644 gi/pygi-repository.c create mode 100644 gi/pygi-repository.h create mode 100644 gi/pygi-struct.c create mode 100644 gi/pygi-struct.h create mode 100644 gi/pygi-type.c create mode 100644 gi/pygi-type.h create mode 100644 gi/pygi.h create mode 100644 gi/pygobject-external.h create mode 100644 gi/repository/Makefile.am create mode 100644 gi/repository/__init__.py create mode 100644 gi/types.py create mode 100644 tests/Makefile.am create mode 100644 tests/libtestgi.c create mode 100644 tests/libtestgi.h create mode 100644 tests/runtests.py create mode 100644 tests/test_gi.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..0d0d8620 --- /dev/null +++ b/.gitignore @@ -0,0 +1,33 @@ +.libs/ +.deps/ +/COPYING +Makefile +Makefile.in +/aclocal.m4 +/autom4te.cache/ +/config.guess +/config.h +/config.h.in +/config.log +/config.status +/config.sub +/configure +/depcomp +/install-sh +/libtool +/ltmain.sh +/m4/ +/missing +/py-compile +/pygi-*.tar.gz +/stamp-h1 + +*.o +*.lo +*.la +*.so +*.pyc +*.gir +*.typelib + +.*.swp diff --git a/Makefile.am b/Makefile.am new file mode 100644 index 00000000..cbe90000 --- /dev/null +++ b/Makefile.am @@ -0,0 +1,10 @@ +ACLOCAL_AMFLAGS = -I m4 + +AM_CFLAGS = \ + -Wall \ + -g + +SUBDIRS = \ + gi \ + tests + diff --git a/autogen.sh b/autogen.sh new file mode 100755 index 00000000..955b5386 --- /dev/null +++ b/autogen.sh @@ -0,0 +1,159 @@ +#!/bin/sh +# Run this to generate all the initial makefiles, etc. + +srcdir=`dirname $0` +test -z "$srcdir" && srcdir=. + +DIE=0 + +if [ -n "$GNOME2_DIR" ]; then + ACLOCAL_FLAGS="-I $GNOME2_DIR/share/aclocal $ACLOCAL_FLAGS" + LD_LIBRARY_PATH="$GNOME2_DIR/lib:$LD_LIBRARY_PATH" + PATH="$GNOME2_DIR/bin:$PATH" + export PATH + export LD_LIBRARY_PATH +fi + +(test -f $srcdir/configure.ac) || { + echo -n "**Error**: Directory "\`$srcdir\'" does not look like the" + echo " top-level package directory" + exit 1 +} + +(autoconf --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`autoconf' installed." + echo "Download the appropriate package for your distribution," + echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +(grep "^IT_PROG_INTLTOOL" $srcdir/configure.ac >/dev/null) && { + (intltoolize --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`intltool' installed." + echo "You can get it from:" + echo " ftp://ftp.gnome.org/pub/GNOME/" + DIE=1 + } +} + +(grep "^AM_PROG_XML_I18N_TOOLS" $srcdir/configure.ac >/dev/null) && { + (xml-i18n-toolize --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`xml-i18n-toolize' installed." + echo "You can get it from:" + echo " ftp://ftp.gnome.org/pub/GNOME/" + DIE=1 + } +} + +(grep "^AM_PROG_LIBTOOL" $srcdir/configure.ac >/dev/null) && { + (libtool --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`libtool' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + } +} + +(grep "^AM_GLIB_GNU_GETTEXT" $srcdir/configure.ac >/dev/null) && { + (grep "sed.*POTFILES" $srcdir/configure.ac) > /dev/null || \ + (glib-gettextize --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`glib' installed." + echo "You can get it from: ftp://ftp.gtk.org/pub/gtk" + DIE=1 + } +} + +(automake --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: You must have \`automake' installed." + echo "You can get it from: ftp://ftp.gnu.org/pub/gnu/" + DIE=1 + NO_AUTOMAKE=yes +} + + +# if no automake, don't bother testing for aclocal +test -n "$NO_AUTOMAKE" || (aclocal --version) < /dev/null > /dev/null 2>&1 || { + echo + echo "**Error**: Missing \`aclocal'. The version of \`automake'" + echo "installed doesn't appear recent enough." + echo "You can get automake from ftp://ftp.gnu.org/pub/gnu/" + DIE=1 +} + +if test "$DIE" -eq 1; then + exit 1 +fi + +if test -z "$*"; then + echo "**Warning**: I am going to run \`configure' with no arguments." + echo "If you wish to pass any to it, please specify them on the" + echo \`$0\'" command line." + echo +fi + +case $CC in +xlc ) + am_opt=--include-deps;; +esac + +for coin in `find $srcdir -path $srcdir/CVS -prune -o -name configure.ac -print` +do + dr=`dirname $coin` + if test -f $dr/NO-AUTO-GEN; then + echo skipping $dr -- flagged as no auto-gen + else + echo processing $dr + ( cd $dr + + aclocalinclude="$ACLOCAL_FLAGS" + + if grep "^AM_GLIB_GNU_GETTEXT" configure.ac >/dev/null; then + echo "Creating $dr/aclocal.m4 ..." + test -r $dr/aclocal.m4 || touch $dr/aclocal.m4 + echo "Running glib-gettextize... Ignore non-fatal messages." + echo "no" | glib-gettextize --force --copy + echo "Making $dr/aclocal.m4 writable ..." + test -r $dr/aclocal.m4 && chmod u+w $dr/aclocal.m4 + fi + if grep "^IT_PROG_INTLTOOL" configure.ac >/dev/null; then + echo "Running intltoolize..." + intltoolize --copy --force --automake + fi + if grep "^AM_PROG_XML_I18N_TOOLS" configure.ac >/dev/null; then + echo "Running xml-i18n-toolize..." + xml-i18n-toolize --copy --force --automake + fi + if grep "^AM_PROG_LIBTOOL" configure.ac >/dev/null; then + if test -z "$NO_LIBTOOLIZE" ; then + echo "Running libtoolize..." + libtoolize --force --copy + fi + fi + echo "Running aclocal $aclocalinclude ..." + aclocal $aclocalinclude + if grep "^A[CM]_CONFIG_HEADER" configure.ac >/dev/null; then + echo "Running autoheader..." + autoheader + fi + echo "Running automake --foreign $am_opt ..." + automake --add-missing --foreign $am_opt + echo "Running autoconf ..." + autoconf + ) + fi +done + +conf_flags="--enable-maintainer-mode" + +if test x$NOCONFIGURE = x; then + echo Running $srcdir/configure $conf_flags "$@" ... + $srcdir/configure $conf_flags "$@" \ + && echo Now type \`make\' to compile. || exit 1 +else + echo Skipping configure process. +fi diff --git a/configure.ac b/configure.ac new file mode 100644 index 00000000..a14eb59e --- /dev/null +++ b/configure.ac @@ -0,0 +1,53 @@ +AC_INIT(pygi, 0.1) + +AM_INIT_AUTOMAKE(foreign) +AC_CONFIG_HEADERS(config.h) +AC_CONFIG_MACRO_DIR(m4) + +m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) + +AM_MAINTAINER_MODE + +AC_ISC_POSIX +AC_PROG_CC +AM_PROG_CC_STDC +AC_HEADER_STDC + +AM_PROG_LIBTOOL + +# Python +AM_PATH_PYTHON(2.5.2) + +AC_PATH_TOOL(PYTHON_CONFIG, "/python${PYTHON_VERSION}-config") +if test -z "$PYTHON_CONFIG"; then + AC_MSG_ERROR(Python development tools not found) +fi +PYTHON_INCLUDES=`$PYTHON_CONFIG --includes` +AC_SUBST(PYTHON_INCLUDES) + +save_CPPFLAGS="${CPPFLAGS}" +CPPFLAGS+="${PYTHON_INCLUDES}" +AC_CHECK_HEADER(Python.h, , AC_MSG_ERROR(Python headers not found)) +CPPFLAGS="${save_CPPFLAGS}" + + +# GNOME +PKG_CHECK_MODULES(GNOME, + glib-2.0 >= 2.22 + gobject-introspection-1.0 >= 0.6.4 + pygobject-2.0 >= 2.20 +) + +INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0` +INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0` + +AC_SUBST(INTROSPECTION_SCANNER) +AC_SUBST(INTROSPECTION_COMPILER) + +AC_OUTPUT( + Makefile + gi/Makefile + gi/repository/Makefile + gi/overrides/Makefile + tests/Makefile +) diff --git a/gi/Makefile.am b/gi/Makefile.am new file mode 100644 index 00000000..2657d3f0 --- /dev/null +++ b/gi/Makefile.am @@ -0,0 +1,50 @@ +PLATFORM_VERSION = 2.0 + +pkgincludedir = $(includedir)/pygtk-$(PLATFORM_VERSION) +pkgpyexecdir = $(pyexecdir)/gtk-2.0 + +SUBDIRS = \ + repository \ + overrides + +pygidir = $(pkgpyexecdir)/gi +pygi_PYTHON = \ + types.py \ + module.py \ + importer.py \ + __init__.py + +_gi_la_CFLAGS = \ + $(PYTHON_INCLUDES) \ + $(GNOME_CFLAGS) +_gi_la_LDFLAGS = \ + -module \ + -avoid-version \ + -export-symbols-regex init_gi +_gi_la_LIBADD = \ + $(GNOME_LIBS) +_gi_la_SOURCES = \ + pygi-repository.c \ + pygi-repository.h \ + pygi-info.c \ + pygi-info.h \ + pygi-struct.c \ + pygi-struct.h \ + pygi-argument.c \ + pygi-argument.h \ + pygi-type.c \ + pygi-type.h \ + pygi.h \ + pygi-private.h \ + pygobject-external.h \ + gimodule.c + +pygi_LTLIBRARIES = _gi.la + +.la.so: + $(LN_S) .libs/$@ $@ || true + +all: $(pygi_LTLIBRARIES:.la=.so) +clean-local: + rm -f $(pygi_LTLIBRARIES:.la=.so) + diff --git a/gi/__init__.py b/gi/__init__.py new file mode 100644 index 00000000..3edea9f0 --- /dev/null +++ b/gi/__init__.py @@ -0,0 +1,24 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab +# +# Copyright (C) 2005-2009 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# USA + +from __future__ import absolute_import + +from ._gi import _API + diff --git a/gi/gimodule.c b/gi/gimodule.c new file mode 100644 index 00000000..d9ee17bd --- /dev/null +++ b/gi/gimodule.c @@ -0,0 +1,144 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 Johan Dahlin + * + * gimodule.c: wrapper for the gobject-introspection library. + * + * 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "pygi-private.h" + +#include + +static PyObject * +_wrap_pyg_enum_add (PyObject *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "g_type", NULL }; + PyObject *py_g_type; + GType g_type; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!:enum_add", + kwlist, &PyGTypeWrapper_Type, &py_g_type)) { + return NULL; + } + + g_type = pyg_type_from_object(py_g_type); + if (g_type == G_TYPE_INVALID) { + return NULL; + } + + return pyg_enum_add(NULL, g_type_name(g_type), NULL, g_type); +} + +static PyObject * +_wrap_pyg_flags_add (PyObject *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "g_type", NULL }; + PyObject *py_g_type; + GType g_type; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!:flags_add", + kwlist, &PyGTypeWrapper_Type, &py_g_type)) { + return NULL; + } + + g_type = pyg_type_from_object(py_g_type); + if (g_type == G_TYPE_INVALID) { + return NULL; + } + + return pyg_flags_add(NULL, g_type_name(g_type), NULL, g_type); +} + +static PyObject * +_wrap_pyg_set_object_has_new_constructor (PyObject *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "g_type", NULL }; + PyObject *py_g_type; + GType g_type; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "O!:set_object_has_new_constructor", + kwlist, &PyGTypeWrapper_Type, &py_g_type)) { + return NULL; + } + + g_type = pyg_type_from_object(py_g_type); + if (!g_type_is_a(g_type, G_TYPE_OBJECT)) { + PyErr_SetString(PyExc_TypeError, "must be a subtype of GObject"); + return NULL; + } + + pyg_set_object_has_new_constructor(g_type); + + Py_RETURN_NONE; +} + + +static PyMethodDef _pygi_functions[] = { + { "enum_add", (PyCFunction)_wrap_pyg_enum_add, METH_VARARGS | METH_KEYWORDS }, + { "flags_add", (PyCFunction)_wrap_pyg_flags_add, METH_VARARGS | METH_KEYWORDS }, + + { "set_object_has_new_constructor", (PyCFunction)_wrap_pyg_set_object_has_new_constructor, METH_VARARGS | METH_KEYWORDS }, + { NULL, NULL, 0 } +}; + +struct PyGI_API PyGI_API = { + pygi_type_import_by_g_type +}; + + +PyMODINIT_FUNC +init_gi(void) +{ + PyObject *m; + PyObject *api; + + m = Py_InitModule("_gi", _pygi_functions); + if (m == NULL) { + return; + } + + if (pygobject_init(-1, -1, -1) == NULL) { + return; + } + + if (_pygobject_import() < 0) { + return; + } + + _pygi_repository_register_types(m); + _pygi_info_register_types(m); + _pygi_struct_register_types(m); + _pygi_argument_init(); + + api = PyCObject_FromVoidPtr((void *)&PyGI_API, NULL); + if (api == NULL) { + return; + } + PyModule_AddObject(m, "_API", api); +} + diff --git a/gi/importer.py b/gi/importer.py new file mode 100644 index 00000000..48392b42 --- /dev/null +++ b/gi/importer.py @@ -0,0 +1,89 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab +# +# Copyright (C) 2005-2009 Johan Dahlin +# +# importer.py: dynamic importer for introspected libraries. +# +# 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# USA + +from __future__ import absolute_import + +import sys +import gobject + +from ._gi import Repository, RepositoryError +from .module import DynamicModule + + +repository = Repository.get_default() + + +class DynamicImporter(object): + + # Note: see PEP302 for the Importer Protocol implemented below. + + def __init__(self, path): + self.path = path + + def find_module(self, fullname, path=None): + if not fullname.startswith(self.path): + return + + path, namespace = fullname.rsplit('.', 1) + if path != self.path: + return + try: + repository.require(namespace) + except RepositoryError: + pass + else: + return self + + def load_module(self, fullname): + if fullname in sys.modules: + return sys.modules[name] + + path, namespace = fullname.rsplit('.', 1) + + # Workaround for GObject + if namespace == 'GObject': + sys.modules[fullname] = gobject + return gobject + + # Look for an overrides module + overrides_name = 'gi.overrides.%s' % namespace + try: + overrides_type_name = '%sModule' % namespace + overrides_module = __import__(overrides_name, fromlist=[overrides_type_name]) + module_type = getattr(overrides_module, overrides_type_name) + except ImportError, e: + module_type = DynamicModule + + module = module_type.__new__(module_type) + module.__dict__ = { + '__file__': '<%s>' % fullname, + '__name__': fullname, + '__namespace__': namespace, + '__loader__': self + } + + sys.modules[fullname] = module + + module.__init__() + + return module + diff --git a/gi/module.py b/gi/module.py new file mode 100644 index 00000000..1a549712 --- /dev/null +++ b/gi/module.py @@ -0,0 +1,167 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab +# +# Copyright (C) 2007-2009 Johan Dahlin +# +# module.py: dynamic module for introspected libraries. +# +# 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# USA + +from __future__ import absolute_import + +import os +import gobject + +from ._gi import \ + Repository, \ + FunctionInfo, \ + RegisteredTypeInfo, \ + EnumInfo, \ + ObjectInfo, \ + InterfaceInfo, \ + ConstantInfo, \ + StructInfo, \ + Struct, \ + enum_add, \ + flags_add +from .types import \ + GObjectMeta, \ + StructMeta, \ + Boxed, \ + Function + +repository = Repository.get_default() + + +def get_parent_for_object(object_info): + parent_object_info = object_info.get_parent() + + if not parent_object_info: + return object + + namespace = parent_object_info.get_namespace() + name = parent_object_info.get_name() + + # Workaround for GObject.Object and GObject.InitiallyUnowned. + if namespace == 'GObject' and name == 'Object' or name == 'InitiallyUnowned': + return gobject.GObject + + module = __import__('gi.repository.%s' % namespace, fromlist=[name]) + return getattr(module, name) + +def get_interfaces_for_object(object_info): + interfaces = [] + for interface_info in object_info.get_interfaces(): + namespace = interface_info.get_namespace() + name = interface_info.get_name() + + module = __import__('gi.repository.%s' % namespace, fromlist=[name]) + interfaces.append(getattr(module, name)) + return interfaces + + +class DynamicModule(object): + + def __str__(self): + path = repository.get_typelib_path(self.__namespace__) + return "" % (self.__name__, path) + + def __getattr__(self, name): + if self.__dict__.has_key(name): + return self.__dict__[name] + + info = repository.find_by_name(self.__namespace__, name) + if not info: + raise AttributeError("%r object has no attribute %r" % ( + self.__class__.__name__, name)) + + if isinstance(info, EnumInfo): + g_type = info.get_g_type() + value = g_type.pytype + + if value is None: + if g_type.is_a(gobject.TYPE_ENUM): + value = enum_add(g_type) + else: + value = flags_add(g_type) + + value.__info__ = info + value.__module__ = info.get_namespace() + + for value_info in info.get_values(): + name = value_info.get_name().upper() + setattr(value, name, value(value_info.get_value())) + + elif isinstance(info, RegisteredTypeInfo): + g_type = info.get_g_type() + + # Check if there is already a Python wrapper. + if g_type != gobject.TYPE_NONE: + type_ = g_type.pytype + if type_ is not None: + self.__dict__[name] = type_ + return type_ + + # Create a wrapper. + if isinstance(info, ObjectInfo): + parent = get_parent_for_object(info) + interfaces = tuple(interface for interface in get_interfaces_for_object(info) + if not issubclass(parent, interface)) + bases = (parent,) + interfaces + metaclass = GObjectMeta + elif isinstance(info, InterfaceInfo): + bases = (gobject.GInterface,) + metaclass = GObjectMeta + elif isinstance(info, StructInfo): + if g_type.is_a(gobject.TYPE_BOXED): + bases = (Boxed,) + elif g_type.is_a(gobject.TYPE_POINTER) or g_type == gobject.TYPE_NONE: + bases = (Struct,) + else: + raise TypeError, "unable to create a wrapper for %s.%s" % (info.get_namespace(), info.get_name()) + metaclass = StructMeta + else: + raise NotImplementedError(info) + + name = info.get_name() + dict_ = { + '__info__': info, + '__module__': self.__namespace__, + '__gtype__': g_type + } + value = metaclass(name, bases, dict_) + + # Register the new Python wrapper. + if g_type != gobject.TYPE_NONE: + g_type.pytype = value + + elif isinstance(info, FunctionInfo): + value = Function(info) + elif isinstance(info, ConstantInfo): + value = info.get_value() + else: + raise NotImplementedError(info) + + self.__dict__[name] = value + return value + + @property + def __members__(self): + r = [] + for type_info in repository.get_infos(self.__namespace__): + r.append(type_info.get_name()) + return r + diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py new file mode 100644 index 00000000..e3e2d291 --- /dev/null +++ b/gi/overrides/Gdk.py @@ -0,0 +1,21 @@ +import sys + +from ..module import DynamicModule + +class GdkModule(DynamicModule): + + def __init__(self): + super(GdkModule, self).__init__() + + initialized, argv = self.init_check(tuple(sys.argv)) + if not initialized: + raise RuntimeError("Gdk couldn't be initialized") + + def rectangle_new(self, x, y, width, height): + rectangle = self.Rectangle() + rectangle.x = x + rectangle.y = y + rectangle.width = width + rectangle.height = height + return rectangle + diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py new file mode 100644 index 00000000..3de0e7e1 --- /dev/null +++ b/gi/overrides/Gtk.py @@ -0,0 +1,13 @@ +import sys + +from ..module import DynamicModule + +class GtkModule(DynamicModule): + + def __init__(self): + super(GtkModule, self).__init__() + + initialized, argv = self.init_check(tuple(sys.argv)) + if not initialized: + raise RuntimeError("Gtk couldn't be initialized") + diff --git a/gi/overrides/Makefile.am b/gi/overrides/Makefile.am new file mode 100644 index 00000000..1c3bee78 --- /dev/null +++ b/gi/overrides/Makefile.am @@ -0,0 +1,10 @@ +PLATFORM_VERSION = 2.0 + +pkgpyexecdir = $(pyexecdir)/gtk-2.0/gi + +pygioverridesdir = $(pkgpyexecdir)/overrides +pygioverrides_PYTHON = \ + Gtk.py \ + Gdk.py \ + __init__.py + diff --git a/gi/overrides/__init__.py b/gi/overrides/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c new file mode 100644 index 00000000..34d68e24 --- /dev/null +++ b/gi/pygi-argument.c @@ -0,0 +1,1976 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 Johan Dahlin + * + * pygi-argument.c: GArgument - PyObject conversion functions. + * + * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "pygi-private.h" + +#include +#include + +#include +#include + +static void +_pygi_g_type_tag_py_bounds (GITypeTag type_tag, + PyObject **lower, + PyObject **upper) +{ + switch(type_tag) { + case GI_TYPE_TAG_INT8: + *lower = PyInt_FromLong(-128); + *upper = PyInt_FromLong(127); + break; + case GI_TYPE_TAG_UINT8: + *upper = PyInt_FromLong(255); + *lower = PyInt_FromLong(0); + break; + case GI_TYPE_TAG_INT16: + *lower = PyInt_FromLong(-32768); + *upper = PyInt_FromLong(32767); + break; + case GI_TYPE_TAG_UINT16: + *upper = PyInt_FromLong(65535); + *lower = PyInt_FromLong(0); + break; + case GI_TYPE_TAG_INT32: + *lower = PyInt_FromLong(-2147483648); + *upper = PyInt_FromLong(2147483647); + break; + case GI_TYPE_TAG_UINT32: + /* Note: On 32-bit archs, this number doesn't fit in a long. */ + *upper = PyLong_FromLongLong(4294967295); + *lower = PyInt_FromLong(0); + break; + case GI_TYPE_TAG_INT64: + /* Note: On 32-bit archs, these numbers don't fit in a long. */ + *lower = PyLong_FromLongLong(-9223372036854775808u); + *upper = PyLong_FromLongLong(9223372036854775807); + break; + case GI_TYPE_TAG_UINT64: + *upper = PyLong_FromUnsignedLongLong(18446744073709551615u); + *lower = PyInt_FromLong(0); + break; + case GI_TYPE_TAG_SHORT: + *lower = PyInt_FromLong(G_MINSHORT); + *upper = PyInt_FromLong(G_MAXSHORT); + break; + case GI_TYPE_TAG_USHORT: + *upper = PyInt_FromLong(G_MAXUSHORT); + *lower = PyInt_FromLong(0); + break; + case GI_TYPE_TAG_INT: + *lower = PyInt_FromLong(G_MININT); + *upper = PyInt_FromLong(G_MAXINT); + break; + case GI_TYPE_TAG_UINT: + /* Note: On 32-bit archs, this number doesn't fit in a long. */ + *upper = PyLong_FromLongLong(G_MAXUINT); + *lower = PyInt_FromLong(0); + break; + case GI_TYPE_TAG_LONG: + case GI_TYPE_TAG_SSIZE: + *lower = PyInt_FromLong(G_MINLONG); + *upper = PyInt_FromLong(G_MAXLONG); + break; + case GI_TYPE_TAG_ULONG: + case GI_TYPE_TAG_SIZE: + *upper = PyLong_FromUnsignedLongLong(G_MAXULONG); + *lower = PyInt_FromLong(0); + break; + case GI_TYPE_TAG_FLOAT: + *upper = PyFloat_FromDouble(G_MAXFLOAT); + *lower = PyFloat_FromDouble(-G_MAXFLOAT); + break; + case GI_TYPE_TAG_DOUBLE: + *upper = PyFloat_FromDouble(G_MAXDOUBLE); + *lower = PyFloat_FromDouble(-G_MAXDOUBLE); + break; + default: + PyErr_SetString(PyExc_TypeError, "Non-numeric type tag"); + *lower = *upper = NULL; + return; + } +} + +gint +_pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, + gboolean is_instance, + PyObject *object) +{ + gint retval; + + GType g_type; + PyObject *py_type; + gchar *type_name_expected = NULL; + + g_type = g_registered_type_info_get_g_type(info); + + if (g_type != G_TYPE_NONE) { + py_type = _pygi_type_get_from_g_type(g_type); + } else { + py_type = _pygi_type_import_by_gi_info((GIBaseInfo *)info); + } + + if (py_type == NULL) { + return FALSE; + } + + g_assert(PyType_Check(py_type)); + + if (is_instance) { + retval = PyObject_IsInstance(object, py_type); + if (!retval) { + type_name_expected = _pygi_g_base_info_get_fullname( + (GIBaseInfo *)info); + } + } else { + if (!PyObject_Type(py_type)) { + type_name_expected = "type"; + retval = 0; + } else if (!PyType_IsSubtype((PyTypeObject *)object, + (PyTypeObject *)py_type)) { + type_name_expected = _pygi_g_base_info_get_fullname( + (GIBaseInfo *)info); + retval = 0; + } else { + retval = 1; + } + } + + Py_DECREF(py_type); + + if (!retval) { + PyTypeObject *object_type; + + if (type_name_expected == NULL) { + return -1; + } + + object_type = (PyTypeObject *)PyObject_Type(object); + if (object_type == NULL) { + return -1; + } + + PyErr_Format(PyExc_TypeError, "Must be %s, not %s", + type_name_expected, object_type->tp_name); + + g_free(type_name_expected); + } + + return retval; +} + +gint +_pygi_g_type_info_check_object (GITypeInfo *type_info, + gboolean may_be_null, + PyObject *object) +{ + GITypeTag type_tag; + gboolean is_pointer; + gint retval = 1; + + type_tag = g_type_info_get_tag(type_info); + is_pointer = g_type_info_is_pointer(type_info); + + if (is_pointer && may_be_null && object == Py_None) { + return retval; + } + + switch (type_tag) { + case GI_TYPE_TAG_VOID: + if (object != Py_None) { + PyErr_Format(PyExc_TypeError, "Must be %s, not %s", + Py_None->ob_type->tp_name, object->ob_type->tp_name); + retval = 0; + } + break; + case GI_TYPE_TAG_BOOLEAN: + /* No check; every Python object has a truth value. */ + break; + case GI_TYPE_TAG_INT8: + case GI_TYPE_TAG_UINT8: + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_UINT16: + case GI_TYPE_TAG_INT32: + case GI_TYPE_TAG_UINT32: + case GI_TYPE_TAG_INT64: + case GI_TYPE_TAG_UINT64: + case GI_TYPE_TAG_SHORT: + case GI_TYPE_TAG_USHORT: + case GI_TYPE_TAG_INT: + case GI_TYPE_TAG_UINT: + case GI_TYPE_TAG_LONG: + case GI_TYPE_TAG_ULONG: + case GI_TYPE_TAG_SSIZE: + case GI_TYPE_TAG_SIZE: + case GI_TYPE_TAG_FLOAT: + case GI_TYPE_TAG_DOUBLE: + { + PyObject *number, *lower, *upper; + + if (!PyNumber_Check(object)) { + PyErr_Format(PyExc_TypeError, "Must be number, not %s", + object->ob_type->tp_name); + retval = 0; + break; + } + + if (type_tag == GI_TYPE_TAG_FLOAT || type_tag == GI_TYPE_TAG_DOUBLE) { + number = PyNumber_Float(object); + } else { + number = PyNumber_Int(object); + } + + _pygi_g_type_tag_py_bounds(type_tag, &lower, &upper); + + if (lower == NULL || upper == NULL || number == NULL) { + retval = -1; + goto check_number_release; + } + + /* Check bounds */ + if (PyObject_Compare(lower, number) > 0 + || PyObject_Compare(upper, number) < 0) { + PyObject *lower_str; + PyObject *upper_str; + + if (PyErr_Occurred()) { + retval = -1; + goto check_number_release; + } + + lower_str = PyObject_Str(lower); + upper_str = PyObject_Str(upper); + if (lower_str == NULL || upper_str == NULL) { + retval = -1; + goto check_number_error_release; + } + + PyErr_Format(PyExc_ValueError, "Must range from %s to %s", + PyString_AS_STRING(lower_str), + PyString_AS_STRING(upper_str)); + + retval = 0; + +check_number_error_release: + Py_XDECREF(lower_str); + Py_XDECREF(upper_str); + } + +check_number_release: + Py_XDECREF(number); + Py_XDECREF(lower); + Py_XDECREF(upper); + break; + } + case GI_TYPE_TAG_TIME_T: + if (!PyDateTime_Check(object)) { + PyErr_Format(PyExc_TypeError, "Must be datetime.datetime, not %s", + object->ob_type->tp_name); + retval = 0; + break; + } + break; + case GI_TYPE_TAG_GTYPE: + { + gint is_instance; + + is_instance = PyObject_IsInstance(object, (PyObject *)&PyGTypeWrapper_Type); + if (is_instance < 0) { + retval = -1; + break; + } + + if (!is_instance && (!PyType_Check(object) || pyg_type_from_object(object) == 0)) { + PyErr_Format(PyExc_TypeError, "Must be gobject.GType, not %s", + object->ob_type->tp_name); + retval = 0; + } + break; + } + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + if (!PyString_Check(object) && (!may_be_null || object != Py_None)) { + PyErr_Format(PyExc_TypeError, "Must be string, not %s", + object->ob_type->tp_name); + retval = 0; + } + break; + case GI_TYPE_TAG_ARRAY: + { + gssize fixed_size; + Py_ssize_t length; + GITypeInfo *item_type_info; + Py_ssize_t i; + + if (!PySequence_Check(object)) { + PyErr_Format(PyExc_TypeError, "Must be sequence, not %s", + object->ob_type->tp_name); + retval = 0; + break; + } + + length = PySequence_Length(object); + if (length < 0) { + retval = -1; + break; + } + + fixed_size = g_type_info_get_array_fixed_size(type_info); + if (fixed_size >= 0 && length != fixed_size) { + PyErr_Format(PyExc_ValueError, "Must contain %zd items, not %zd", + fixed_size, length); + retval = 0; + break; + } + + item_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(item_type_info != NULL); + + for (i = 0; i < length; i++) { + PyObject *item; + + item = PySequence_GetItem(object, i); + if (item == NULL) { + retval = -1; + break; + } + + retval = _pygi_g_type_info_check_object(item_type_info, FALSE, item); + + Py_DECREF(item); + + if (retval < 0) { + break; + } + if (!retval) { + _PyGI_ERROR_PREFIX("Item %zd: ", i); + break; + } + } + + g_base_info_unref((GIBaseInfo *)item_type_info); + + break; + } + case GI_TYPE_TAG_INTERFACE: + { + GIBaseInfo *info; + GIInfoType info_type; + + info = g_type_info_get_interface(type_info); + g_assert(info != NULL); + + info_type = g_base_info_get_type(info); + + switch (info_type) { + case GI_INFO_TYPE_CALLBACK: + /* TODO */ + PyErr_SetString(PyExc_NotImplementedError, "callback marshalling is not supported yet"); + break; + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + retval = _pygi_g_registered_type_info_check_object((GIRegisteredTypeInfo *)info, TRUE, object); + break; + case GI_INFO_TYPE_STRUCT: + { + GType type; + + /* Handle special cases. */ + type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info); + if (g_type_is_a(type, G_TYPE_VALUE)) { + GType object_type; + object_type = pyg_type_from_object((PyObject *)object->ob_type); + if (object_type == G_TYPE_INVALID) { + PyErr_Format(PyExc_TypeError, "Must be of a known GType, not %s", + object->ob_type->tp_name); + retval = 0; + } + break; + } else if (g_type_is_a(type, G_TYPE_CLOSURE)) { + if (!PyCallable_Check(object)) { + PyErr_Format(PyExc_TypeError, "Must be callable, not %s", + object->ob_type->tp_name); + retval = 0; + } + break; + } + + /* Fallback. */ + } + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_OBJECT: + retval = _pygi_g_registered_type_info_check_object((GIRegisteredTypeInfo *)info, TRUE, object); + break; + case GI_INFO_TYPE_UNION: + /* TODO */ + PyErr_SetString(PyExc_NotImplementedError, "union marshalling is not supported yet"); + break; + default: + g_assert_not_reached(); + } + + g_base_info_unref(info); + break; + } + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + { + Py_ssize_t length; + GITypeInfo *item_type_info; + Py_ssize_t i; + + if (!PySequence_Check(object)) { + PyErr_Format(PyExc_TypeError, "Must be sequence, not %s", + object->ob_type->tp_name); + retval = 0; + break; + } + + length = PySequence_Length(object); + if (length < 0) { + retval = -1; + break; + } + + item_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(item_type_info != NULL); + + for (i = 0; i < length; i++) { + PyObject *item; + + item = PySequence_GetItem(object, i); + if (item == NULL) { + retval = -1; + break; + } + + retval = _pygi_g_type_info_check_object(item_type_info, FALSE, item); + + Py_DECREF(item); + + if (retval < 0) { + break; + } + if (!retval) { + _PyGI_ERROR_PREFIX("Item %zd: ", i); + break; + } + } + + g_base_info_unref((GIBaseInfo *)item_type_info); + break; + } + case GI_TYPE_TAG_GHASH: + { + Py_ssize_t length; + PyObject *keys; + PyObject *values; + GITypeInfo *key_type_info; + GITypeInfo *value_type_info; + Py_ssize_t i; + + if (!PyMapping_Check(object)) { + PyErr_Format(PyExc_TypeError, "Must be mapping, not %s", + object->ob_type->tp_name); + retval = 0; + break; + } + + length = PyMapping_Length(object); + if (length < 0) { + retval = -1; + break; + } + + keys = PyMapping_Keys(object); + if (keys == NULL) { + retval = -1; + break; + } + + values = PyMapping_Values(object); + if (values == NULL) { + retval = -1; + Py_DECREF(keys); + break; + } + + key_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(key_type_info != NULL); + + value_type_info = g_type_info_get_param_type(type_info, 1); + g_assert(value_type_info != NULL); + + for (i = 0; i < length; i++) { + PyObject *key; + PyObject *value; + + key = PyList_GET_ITEM(keys, i); + value = PyList_GET_ITEM(values, i); + + retval = _pygi_g_type_info_check_object(key_type_info, FALSE, key); + if (retval < 0) { + break; + } + if (!retval) { + _PyGI_ERROR_PREFIX("Key %zd :", i); + break; + } + + retval = _pygi_g_type_info_check_object(value_type_info, FALSE, value); + if (retval < 0) { + break; + } + if (!retval) { + _PyGI_ERROR_PREFIX("Value %zd :", i); + break; + } + } + + g_base_info_unref((GIBaseInfo *)key_type_info); + g_base_info_unref((GIBaseInfo *)value_type_info); + Py_DECREF(values); + Py_DECREF(keys); + break; + } + case GI_TYPE_TAG_ERROR: + PyErr_SetString(PyExc_NotImplementedError, "Error marshalling is not supported yet"); + /* TODO */ + break; + } + + return retval; +} + +GArray * +_pygi_argument_to_array (GArgument *arg, + GArgument *args[], + GITypeInfo *type_info) +{ + GITypeInfo *item_type_info; + gboolean is_zero_terminated; + gsize item_size; + gssize length; + GArray *g_array; + + is_zero_terminated = g_type_info_is_zero_terminated(type_info); + item_type_info = g_type_info_get_param_type(type_info, 0); + + item_size = _pygi_g_type_info_size(item_type_info); + + g_base_info_unref((GIBaseInfo *)item_type_info); + + if (is_zero_terminated) { + length = g_strv_length(arg->v_pointer); + } else { + length = g_type_info_get_array_fixed_size(type_info); + if (length < 0) { + gint length_arg_pos; + + length_arg_pos = g_type_info_get_array_length(type_info); + g_assert(length_arg_pos >= 0); + + /* FIXME: Take into account the type of the argument. */ + length = args[length_arg_pos]->v_int; + } + } + + g_array = g_array_new(is_zero_terminated, FALSE, item_size); + + g_array->data = arg->v_pointer; + g_array->len = length; + + return g_array; +} + +GArgument +_pygi_argument_from_object (PyObject *object, + GITypeInfo *type_info, + GITransfer transfer) +{ + GArgument arg; + GITypeTag type_tag; + gboolean is_pointer; + + type_tag = g_type_info_get_tag(type_info); + is_pointer = g_type_info_is_pointer(type_info); + + if (object == Py_None && is_pointer + && type_tag != GI_TYPE_TAG_BOOLEAN) { /* We want None == FALSE. */ + arg.v_pointer = NULL; + return arg; + } + + switch (type_tag) { + case GI_TYPE_TAG_VOID: + arg.v_pointer = NULL; + break; + case GI_TYPE_TAG_BOOLEAN: + { + gboolean value; + + value = PyObject_IsTrue(object); + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(gboolean, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(gboolean *)arg.v_pointer = value; + } else { + arg.v_boolean = value; + } + + break; + } + case GI_TYPE_TAG_INT8: + case GI_TYPE_TAG_UINT8: + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_UINT16: + case GI_TYPE_TAG_INT32: + case GI_TYPE_TAG_SHORT: + case GI_TYPE_TAG_USHORT: + case GI_TYPE_TAG_INT: + case GI_TYPE_TAG_LONG: + case GI_TYPE_TAG_SSIZE: + { + PyObject *int_; + glong value; + + int_ = PyNumber_Int(object); + if (int_ == NULL) { + break; + } + + value = PyInt_AsLong(int_); + Py_DECREF(int_); + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(glong, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(glong *)arg.v_pointer = value; + } else { + arg.v_long = value; + } + + break; + } + case GI_TYPE_TAG_UINT32: + case GI_TYPE_TAG_UINT64: + case GI_TYPE_TAG_UINT: + case GI_TYPE_TAG_ULONG: + case GI_TYPE_TAG_SIZE: + { + PyObject *number; + guint64 value; + + number = PyNumber_Int(object); + if (number == NULL) { + break; + } + + if (PyInt_Check(number)) { + value = PyInt_AS_LONG(number); + } else { + value = PyLong_AsUnsignedLongLong(number); + } + + Py_DECREF(number); + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(guint64, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(guint64 *)arg.v_pointer = value; + } else { + arg.v_uint64 = value; + } + + break; + } + case GI_TYPE_TAG_INT64: + { + PyObject *number; + gint64 value; + + number = PyNumber_Int(object); + if (number == NULL) { + break; + } + + if (PyInt_Check(number)) { + value = PyInt_AS_LONG(number); + } else { + value = PyLong_AsLongLong(number); + } + + Py_DECREF(number); + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(gint64, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(gint64 *)arg.v_pointer = value; + } else { + arg.v_int64 = value; + } + + break; + } + case GI_TYPE_TAG_FLOAT: + { + PyObject *float_; + gfloat value; + + float_ = PyNumber_Float(object); + if (float_ == NULL) { + break; + } + + value = (float)PyFloat_AsDouble(float_); + Py_DECREF(float_); + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(gfloat, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(gfloat *)arg.v_pointer = value; + } else { + arg.v_float = value; + } + + break; + } + case GI_TYPE_TAG_DOUBLE: + { + PyObject *float_; + gdouble value; + + float_ = PyNumber_Float(object); + if (float_ == NULL) { + break; + } + + value = PyFloat_AsDouble(float_); + Py_DECREF(float_); + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(gdouble, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(gdouble *)arg.v_pointer = value; + } else { + arg.v_double = value; + } + + break; + } + case GI_TYPE_TAG_TIME_T: + { + PyDateTime_DateTime *py_datetime; + struct tm datetime; + time_t time_; + + py_datetime = (PyDateTime_DateTime *)object; + + if (py_datetime->hastzinfo) { + if (PyErr_WarnEx(NULL, "tzinfo ignored; only local time is supported", 1) < 0) { + break; + } + } + + datetime.tm_sec = PyDateTime_DATE_GET_SECOND(py_datetime); + datetime.tm_min = PyDateTime_DATE_GET_MINUTE(py_datetime); + datetime.tm_hour = PyDateTime_DATE_GET_HOUR(py_datetime); + datetime.tm_mday = PyDateTime_GET_DAY(py_datetime); + datetime.tm_mon = PyDateTime_GET_MONTH(py_datetime) - 1; + datetime.tm_year = PyDateTime_GET_YEAR(py_datetime) - 1900; + datetime.tm_isdst = -1; + + time_ = mktime(&datetime); + if (time_ == -1) { + PyErr_SetString(PyExc_RuntimeError, "datetime conversion failed"); + break; + } + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(time_t, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(time_t *)arg.v_pointer = time_; + } else { + arg.v_long = time_; + } + + break; + } + case GI_TYPE_TAG_GTYPE: + { + GType type; + + type = pyg_type_from_object(object); + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(GType, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(GType *)arg.v_pointer = type; + } else { + arg.v_long = type; + } + + break; + } + case GI_TYPE_TAG_UTF8: + { + const gchar *string; + + g_assert(is_pointer); + + string = PyString_AsString(object); + + /* Don't need to check for errors, since g_strdup is NULL-proof. */ + arg.v_string = g_strdup(string); + break; + } + case GI_TYPE_TAG_FILENAME: + { + GError *error = NULL; + const gchar *string; + + g_assert(is_pointer); + + string = PyString_AsString(object); + if (string == NULL) { + break; + } + + arg.v_string = g_filename_from_utf8(string, -1, NULL, NULL, &error); + if (arg.v_string == NULL) { + PyErr_SetString(PyExc_Exception, error->message); + /* TODO: Convert the error to an exception. */ + } + + break; + } + case GI_TYPE_TAG_ARRAY: + { + Py_ssize_t length; + gboolean is_zero_terminated; + GITypeInfo *item_type_info; + gsize item_size; + GArray *array; + GITransfer item_transfer; + Py_ssize_t i; + + length = PySequence_Length(object); + if (length < 0) { + break; + } + + is_zero_terminated = g_type_info_is_zero_terminated(type_info); + item_type_info = g_type_info_get_param_type(type_info, 0); + + item_size = _pygi_g_type_info_size(item_type_info); + + array = g_array_sized_new(is_zero_terminated, FALSE, item_size, length); + if (array == NULL) { + g_base_info_unref((GIBaseInfo *)item_type_info); + PyErr_NoMemory(); + break; + } + + item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + for (i = 0; i < length; i++) { + PyObject *py_item; + GArgument item; + + py_item = PySequence_GetItem(object, i); + if (py_item == NULL) { + goto array_item_error; + } + + item = _pygi_argument_from_object(py_item, item_type_info, item_transfer); + + Py_DECREF(py_item); + + if (PyErr_Occurred()) { + goto array_item_error; + } + + g_array_insert_val(array, i, item); + continue; + +array_item_error: + /* Free everything we have converted so far. */ + _pygi_argument_release((GArgument *)&array, type_info, + GI_TRANSFER_NOTHING, GI_DIRECTION_IN); + array = NULL; + + _PyGI_ERROR_PREFIX("Item %zd: ", i); + break; + } + + arg.v_pointer = array; + + g_base_info_unref((GIBaseInfo *)item_type_info); + break; + } + case GI_TYPE_TAG_INTERFACE: + { + GIBaseInfo *info; + GIInfoType info_type; + + info = g_type_info_get_interface(type_info); + info_type = g_base_info_get_type(info); + + switch (info_type) { + case GI_INFO_TYPE_CALLBACK: + PyErr_SetString(PyExc_NotImplementedError, "callback marshalling is not supported yet"); + /* TODO */ + break; + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_STRUCT: + { + GType type; + + type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info); + + /* Handle special cases first. */ + if (g_type_is_a(type, G_TYPE_VALUE)) { + GValue *value; + GType object_type; + gint retval; + + object_type = pyg_type_from_object((PyObject *)object->ob_type); + if (object_type == G_TYPE_INVALID) { + PyErr_SetString(PyExc_RuntimeError, "unable to retrieve object's GType"); + break; + } + + g_assert(is_pointer); + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + + value = g_slice_new0(GValue); + g_value_init(value, object_type); + + retval = pyg_value_from_pyobject(value, object); + if (retval < 0) { + g_slice_free(GValue, value); + PyErr_SetString(PyExc_RuntimeError, "PyObject conversion to GValue failed"); + break; + } + + arg.v_pointer = value; + } else if (g_type_is_a(type, G_TYPE_CLOSURE)) { + GClosure *closure; + + g_assert(is_pointer); + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + + closure = pyg_closure_new(object, NULL, NULL); + if (closure == NULL) { + PyErr_SetString(PyExc_RuntimeError, "PyObject conversion to GClosure failed"); + break; + } + + arg.v_pointer = closure; + } else if (g_type_is_a(type, G_TYPE_BOXED)) { + g_assert(is_pointer); + arg.v_pointer = pyg_boxed_get(object, void); + if (transfer == GI_TRANSFER_EVERYTHING) { + arg.v_pointer = g_boxed_copy(type, arg.v_pointer); + } + } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) { + g_warn_if_fail(!is_pointer || transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = pyg_pointer_get(object, void); + } else { + PyErr_Format(PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name(type)); + } + + break; + } + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + { + PyObject *int_; + glong value; + + int_ = PyNumber_Int(object); + if (int_ == NULL) { + break; + } + + value = PyInt_AsLong(int_); + Py_DECREF(int_); + + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + arg.v_pointer = g_try_new(glong, 1); + if (arg.v_pointer == NULL) { + PyErr_NoMemory(); + break; + } + *(glong *)arg.v_pointer = value; + } else { + arg.v_long = value; + } + + break; + } + case GI_INFO_TYPE_OBJECT: + g_assert(is_pointer); + + arg.v_pointer = pygobject_get(object); + if (transfer == GI_TRANSFER_EVERYTHING) { + g_object_ref(arg.v_pointer); + } + + break; + case GI_INFO_TYPE_UNION: + PyErr_SetString(PyExc_NotImplementedError, "union marshalling is not supported yet"); + /* TODO */ + break; + default: + g_assert_not_reached(); + } + g_base_info_unref(info); + break; + } + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + { + Py_ssize_t length; + GITypeInfo *item_type_info; + GSList *list = NULL; + GITransfer item_transfer; + Py_ssize_t i; + + g_assert(is_pointer); + + length = PySequence_Length(object); + if (length < 0) { + break; + } + + item_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(item_type_info != NULL); + + item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + for (i = length - 1; i >= 0; i--) { + PyObject *py_item; + GArgument item; + + py_item = PySequence_GetItem(object, i); + if (py_item == NULL) { + goto list_item_error; + } + + item = _pygi_argument_from_object(py_item, item_type_info, item_transfer); + + Py_DECREF(py_item); + + if (PyErr_Occurred()) { + goto list_item_error; + } + + if (type_tag == GI_TYPE_TAG_GLIST) { + list = (GSList *)g_list_prepend((GList *)list, item.v_pointer); + } else { + list = g_slist_prepend(list, item.v_pointer); + } + + continue; + +list_item_error: + /* Free everything we have converted so far. */ + _pygi_argument_release((GArgument *)&list, type_info, + GI_TRANSFER_NOTHING, GI_DIRECTION_IN); + list = NULL; + + _PyGI_ERROR_PREFIX("Item %zd: ", i); + break; + } + + arg.v_pointer = list; + + g_base_info_unref((GIBaseInfo *)item_type_info); + + break; + } + case GI_TYPE_TAG_GHASH: + { + Py_ssize_t length; + PyObject *keys; + PyObject *values; + GITypeInfo *key_type_info; + GITypeInfo *value_type_info; + GITypeTag key_type_tag; + GHashFunc hash_func; + GEqualFunc equal_func; + GHashTable *hash_table; + GITransfer item_transfer; + Py_ssize_t i; + + g_assert(is_pointer); + + length = PyMapping_Length(object); + if (length < 0) { + break; + } + + keys = PyMapping_Keys(object); + if (keys == NULL) { + break; + } + + values = PyMapping_Values(object); + if (values == NULL) { + Py_DECREF(keys); + break; + } + + key_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(key_type_info != NULL); + + value_type_info = g_type_info_get_param_type(type_info, 1); + g_assert(value_type_info != NULL); + + key_type_tag = g_type_info_get_tag(key_type_info); + + switch(key_type_tag) { + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + hash_func = g_str_hash; + equal_func = g_str_equal; + break; + default: + hash_func = NULL; + equal_func = NULL; + } + + hash_table = g_hash_table_new(hash_func, equal_func); + if (hash_table == NULL) { + PyErr_NoMemory(); + goto hash_table_release; + } + + item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + for (i = 0; i < length; i++) { + PyObject *py_key; + PyObject *py_value; + GArgument key; + GArgument value; + + py_key = PyList_GET_ITEM(keys, i); + py_value = PyList_GET_ITEM(values, i); + + key = _pygi_argument_from_object(py_key, key_type_info, item_transfer); + if (PyErr_Occurred()) { + goto hash_table_item_error; + } + + value = _pygi_argument_from_object(py_value, value_type_info, item_transfer); + if (PyErr_Occurred()) { + _pygi_argument_release(&key, type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); + goto hash_table_item_error; + } + + g_hash_table_insert(hash_table, key.v_pointer, value.v_pointer); + continue; + +hash_table_item_error: + /* Free everything we have converted so far. */ + _pygi_argument_release((GArgument *)&hash_table, type_info, + GI_TRANSFER_NOTHING, GI_DIRECTION_IN); + hash_table = NULL; + + _PyGI_ERROR_PREFIX("Item %zd: ", i); + break; + } + + arg.v_pointer = hash_table; + +hash_table_release: + g_base_info_unref((GIBaseInfo *)key_type_info); + g_base_info_unref((GIBaseInfo *)value_type_info); + Py_DECREF(keys); + Py_DECREF(values); + break; + } + case GI_TYPE_TAG_ERROR: + PyErr_SetString(PyExc_NotImplementedError, "error marshalling is not supported yet"); + /* TODO */ + break; + } + + return arg; +} + +PyObject * +_pygi_argument_to_object (GArgument *arg, + GITypeInfo *type_info, + GITransfer transfer) +{ + GITypeTag type_tag; + gboolean is_pointer; + PyObject *object = NULL; + + type_tag = g_type_info_get_tag(type_info); + is_pointer = g_type_info_is_pointer(type_info); + + if (is_pointer && arg->v_pointer == NULL) { + Py_RETURN_NONE; + } + + switch (type_tag) { + case GI_TYPE_TAG_VOID: + Py_INCREF(Py_None); + object = Py_None; + break; + case GI_TYPE_TAG_BOOLEAN: + { + gboolean value; + value = is_pointer ? *(gboolean *)arg->v_pointer : arg->v_boolean; + object = PyBool_FromLong(value); + break; + } + case GI_TYPE_TAG_INT8: + { + gint8 value; + value = is_pointer ? *(gint8 *)arg->v_pointer : arg->v_int8; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_UINT8: + { + guint8 value; + value = is_pointer ? *(guint8 *)arg->v_pointer : arg->v_uint8; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_INT16: + { + gint16 value; + value = is_pointer ? *(gint16 *)arg->v_pointer : arg->v_int16; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_UINT16: + { + guint16 value; + value = is_pointer ? *(guint16 *)arg->v_pointer : arg->v_uint16; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_INT32: + { + gint32 value; + value = is_pointer ? *(gint32 *)arg->v_pointer : arg->v_int32; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_UINT32: + { + guint32 value; + value = is_pointer ? *(guint32 *)arg->v_pointer : arg->v_uint32; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_INT64: + { + gint64 value; + value = is_pointer ? *(gint64 *)arg->v_pointer : arg->v_int64; + object = PyLong_FromLongLong(value); + break; + } + case GI_TYPE_TAG_UINT64: + { + guint64 value; + value = is_pointer ? *(guint64 *)arg->v_pointer : arg->v_uint64; + object = PyLong_FromUnsignedLongLong(value); + break; + } + case GI_TYPE_TAG_SHORT: + { + gshort value; + value = is_pointer ? *(gshort *)arg->v_pointer : arg->v_short; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_USHORT: + { + gushort value; + value = is_pointer ? *(gushort *)arg->v_pointer : arg->v_ushort; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_INT: + { + gint value; + value = is_pointer ? *(gint *)arg->v_pointer : arg->v_int; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_UINT: + { + guint value; + value = is_pointer ? *(guint *)arg->v_pointer : arg->v_uint; + object = PyLong_FromLongLong(value); + break; + } + case GI_TYPE_TAG_LONG: + { + glong value; + value = is_pointer ? *(glong *)arg->v_pointer : arg->v_long; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_ULONG: + { + gulong value; + value = is_pointer ? *(gulong *)arg->v_pointer : arg->v_ulong; + object = PyLong_FromUnsignedLongLong(value); + break; + } + case GI_TYPE_TAG_SSIZE: + { + gssize value; + value = is_pointer ? *(gssize *)arg->v_pointer : arg->v_ssize; + object = PyInt_FromLong(value); + break; + } + case GI_TYPE_TAG_SIZE: + { + gsize value; + value = is_pointer ? *(gsize *)arg->v_pointer : arg->v_size; + object = PyLong_FromUnsignedLongLong(value); + break; + } + case GI_TYPE_TAG_FLOAT: + { + gfloat value; + value = is_pointer ? *(gfloat *)arg->v_pointer : arg->v_float; + object = PyFloat_FromDouble(value); + break; + } + case GI_TYPE_TAG_DOUBLE: + { + gdouble value; + value = is_pointer ? *(gdouble *)arg->v_pointer : arg->v_double; + object = PyFloat_FromDouble(value); + break; + } + case GI_TYPE_TAG_TIME_T: + { + time_t *time_; + struct tm *datetime; + time_ = is_pointer ? arg->v_pointer : &arg->v_long; + datetime = localtime(time_); + object = PyDateTime_FromDateAndTime( + datetime->tm_year + 1900, + datetime->tm_mon + 1, + datetime->tm_mday, + datetime->tm_hour, + datetime->tm_min, + datetime->tm_sec, + 0); + break; + } + case GI_TYPE_TAG_GTYPE: + { + GType type; + type = is_pointer ? *(GType *)arg->v_pointer : arg->v_long; + object = pyg_type_wrapper_new(type); + break; + } + case GI_TYPE_TAG_UTF8: + g_assert(is_pointer); + object = PyString_FromString(arg->v_string); + break; + case GI_TYPE_TAG_FILENAME: + { + GError *error = NULL; + gchar *string; + + g_assert(is_pointer); + + string = g_filename_to_utf8(arg->v_string, -1, NULL, NULL, &error); + if (string == NULL) { + PyErr_SetString(PyExc_Exception, error->message); + /* TODO: Convert the error to an exception. */ + break; + } + + object = PyString_FromString(string); + + g_free(string); + + break; + } + case GI_TYPE_TAG_ARRAY: + { + GArray *array; + GITypeInfo *item_type_info; + GITransfer item_transfer; + gsize i; + + array = arg->v_pointer; + + object = PyTuple_New(array->len); + if (object == NULL) { + break; + } + + item_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(item_type_info != NULL); + + item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + for(i = 0; i < array->len; i++) { + GArgument item; + PyObject *py_item; + + item = _g_array_index(array, GArgument, i); + py_item = _pygi_argument_to_object(&item, item_type_info, item_transfer); + if (py_item == NULL) { + Py_CLEAR(object); + _PyGI_ERROR_PREFIX("Item %zu: ", i); + break; + } + + PyTuple_SET_ITEM(object, i, py_item); + } + + g_base_info_unref((GIBaseInfo *)item_type_info); + break; + } + case GI_TYPE_TAG_INTERFACE: + { + GIBaseInfo *info; + GIInfoType info_type; + + info = g_type_info_get_interface(type_info); + info_type = g_base_info_get_type(info); + + switch (info_type) { + case GI_INFO_TYPE_CALLBACK: + { + PyErr_SetString(PyExc_NotImplementedError, "callback marshalling is not supported yet"); + /* TODO */ + break; + } + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_STRUCT: + { + GType type; + + type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info); + if (g_type_is_a(type, G_TYPE_VALUE)) { + g_assert(is_pointer); + object = pyg_value_as_pyobject(arg->v_pointer, FALSE); + } else if (g_type_is_a(type, G_TYPE_BOXED)) { + g_assert(is_pointer); + object = pyg_boxed_new(type, arg->v_pointer, FALSE, transfer == GI_TRANSFER_EVERYTHING); + } else if (g_type_is_a(type, G_TYPE_POINTER)) { + PyObject *py_type; + + g_assert(is_pointer); + + py_type = _pygi_type_get_from_g_type(type); + + if (py_type == NULL || !PyType_IsSubtype((PyTypeObject *)type, &PyGIStruct_Type)) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + object = pyg_pointer_new(type, arg->v_pointer); + } else { + object = _pygi_struct_new((PyTypeObject *)py_type, arg->v_pointer, transfer == GI_TRANSFER_EVERYTHING); + } + + Py_XDECREF(py_type); + } else if (type == G_TYPE_NONE) { + PyObject *py_type; + + py_type = _pygi_type_import_by_gi_info(info); + if (py_type == NULL) { + break; + } + + object = _pygi_struct_new((PyTypeObject *)py_type, arg->v_pointer, + transfer == GI_TRANSFER_EVERYTHING); + + Py_DECREF(py_type); + } else { + PyErr_Format(PyExc_NotImplementedError, "structure type '%s' is not supported yet", g_type_name(type)); + } + + break; + } + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + { + GType type; + glong value; + + type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info); + value = is_pointer ? *(glong *)arg->v_pointer : arg->v_long; + + if (info_type == GI_INFO_TYPE_ENUM) { + object = pyg_enum_from_gtype(type, value); + } else { + object = pyg_flags_from_gtype(type, value); + } + + break; + } + case GI_INFO_TYPE_OBJECT: + g_assert(is_pointer); + object = pygobject_new(arg->v_pointer); + break; + case GI_INFO_TYPE_UNION: + /* TODO */ + PyErr_SetString(PyExc_NotImplementedError, "union marshalling is not supported yet"); + break; + default: + g_assert_not_reached(); + } + + g_base_info_unref(info); + break; + } + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + { + GSList *list; + gsize length; + GITypeInfo *item_type_info; + GITransfer item_transfer; + gsize i; + + g_assert(is_pointer); + + list = arg->v_pointer; + length = g_slist_length(list); + + object = PyList_New(length); + if (object == NULL) { + break; + } + + item_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(item_type_info != NULL); + + item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + for (i = 0; list != NULL; list = g_slist_next(list), i++) { + GArgument item; + PyObject *py_item; + + item.v_pointer = list->data; + + py_item = _pygi_argument_to_object(&item, item_type_info, item_transfer); + if (py_item == NULL) { + Py_CLEAR(object); + _PyGI_ERROR_PREFIX("Item %zu: ", i); + break; + } + + PyList_SET_ITEM(object, i, py_item); + } + + g_base_info_unref((GIBaseInfo *)item_type_info); + break; + } + case GI_TYPE_TAG_GHASH: + { + GITypeInfo *key_type_info; + GITypeInfo *value_type_info; + GITransfer item_transfer; + GHashTableIter hash_table_iter; + GArgument key; + GArgument value; + + g_assert(is_pointer); + + object = PyDict_New(); + if (object == NULL) { + break; + } + + key_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(key_type_info != NULL); + + value_type_info = g_type_info_get_param_type(type_info, 1); + g_assert(value_type_info != NULL); + + item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + g_hash_table_iter_init(&hash_table_iter, (GHashTable *)arg->v_pointer); + while (g_hash_table_iter_next(&hash_table_iter, &key.v_pointer, &value.v_pointer)) { + PyObject *py_key; + PyObject *py_value; + int retval; + + py_key = _pygi_argument_to_object(&key, key_type_info, item_transfer); + if (py_key == NULL) { + break; + } + + py_value = _pygi_argument_to_object(&value, value_type_info, item_transfer); + if (py_value == NULL) { + Py_DECREF(py_key); + break; + } + + retval = PyDict_SetItem(object, py_key, py_value); + + Py_DECREF(py_key); + Py_DECREF(py_value); + + if (retval < 0) { + Py_CLEAR(object); + break; + } + } + + g_base_info_unref((GIBaseInfo *)key_type_info); + g_base_info_unref((GIBaseInfo *)value_type_info); + break; + } + case GI_TYPE_TAG_ERROR: + /* Errors should be handled in the invoke wrapper. */ + g_assert_not_reached(); + } + + return object; +} + +void +_pygi_argument_release (GArgument *arg, + GITypeInfo *type_info, + GITransfer transfer, + GIDirection direction) +{ + GITypeTag type_tag; + gboolean is_pointer; + + type_tag = g_type_info_get_tag(type_info); + is_pointer = g_type_info_is_pointer(type_info); + + if (is_pointer && arg->v_pointer == NULL) { + return; + } + + switch(type_tag) { + case GI_TYPE_TAG_VOID: + case GI_TYPE_TAG_BOOLEAN: + case GI_TYPE_TAG_INT8: + case GI_TYPE_TAG_UINT8: + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_UINT16: + case GI_TYPE_TAG_INT32: + case GI_TYPE_TAG_UINT32: + case GI_TYPE_TAG_INT64: + case GI_TYPE_TAG_UINT64: + case GI_TYPE_TAG_SHORT: + case GI_TYPE_TAG_USHORT: + case GI_TYPE_TAG_INT: + case GI_TYPE_TAG_UINT: + case GI_TYPE_TAG_LONG: + case GI_TYPE_TAG_ULONG: + case GI_TYPE_TAG_SSIZE: + case GI_TYPE_TAG_SIZE: + case GI_TYPE_TAG_FLOAT: + case GI_TYPE_TAG_DOUBLE: + case GI_TYPE_TAG_TIME_T: + case GI_TYPE_TAG_GTYPE: + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) + || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { + g_free(arg->v_pointer); + } + } + break; + case GI_TYPE_TAG_FILENAME: + case GI_TYPE_TAG_UTF8: + g_assert(is_pointer); + if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) + || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { + g_free(arg->v_string); + } + break; + case GI_TYPE_TAG_ARRAY: + { + GArray *array; + gsize i; + + g_assert(is_pointer); + + array = arg->v_pointer; + + if ((direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) + || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { + GITypeInfo *item_type_info; + GITransfer item_transfer; + + item_type_info = g_type_info_get_param_type(type_info, 0); + + item_transfer = direction == GI_DIRECTION_IN ? GI_TRANSFER_NOTHING : GI_TRANSFER_EVERYTHING; + + /* Free the items */ + for (i = 0; i < array->len; i++) { + GArgument item; + item = _g_array_index(array, GArgument, i); + _pygi_argument_release(&item, item_type_info, item_transfer, direction); + } + + g_base_info_unref((GIBaseInfo *)item_type_info); + } + + if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) + || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { + g_array_free(array, TRUE); + } + + break; + } + case GI_TYPE_TAG_INTERFACE: + { + GIBaseInfo *info; + GIInfoType info_type; + + info = g_type_info_get_interface(type_info); + info_type = g_base_info_get_type(info); + + switch (info_type) { + case GI_INFO_TYPE_CALLBACK: + /* TODO */ + break; + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_STRUCT: + { + GType type; + + type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info); + + if (g_type_is_a(type, G_TYPE_VALUE)) { + GValue *value; + + g_assert(is_pointer); + + value = arg->v_pointer; + + if ((direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) + || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { + g_value_unset(value); + } + + if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) + || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { + g_slice_free(GValue, value); + } + } else if (g_type_is_a(type, G_TYPE_CLOSURE)) { + g_assert(is_pointer); + if (direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) { + g_closure_unref(arg->v_pointer); + } + } else if (g_type_is_a(type, G_TYPE_BOXED)) { + g_assert(is_pointer); + } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) { + g_warn_if_fail(!is_pointer || transfer == GI_TRANSFER_NOTHING); + } + + break; + } + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + if (is_pointer) { + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) + || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { + g_free(arg->v_pointer); + } + } + break; + case GI_INFO_TYPE_OBJECT: + g_assert(is_pointer); + if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING) { + g_object_unref(arg->v_pointer); + } + break; + case GI_INFO_TYPE_UNION: + /* TODO */ + break; + default: + g_assert_not_reached(); + } + + g_base_info_unref(info); + break; + } + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + { + GSList *list; + + g_assert(is_pointer); + + list = arg->v_pointer; + + if ((direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) + || (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_EVERYTHING)) { + GITypeInfo *item_type_info; + GITransfer item_transfer; + GSList *item; + + item_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(item_type_info != NULL); + + item_transfer = direction == GI_DIRECTION_IN ? GI_TRANSFER_NOTHING : GI_TRANSFER_EVERYTHING; + + /* Free the items */ + for (item = list; item != NULL; item = g_slist_next(item)) { + _pygi_argument_release((GArgument *)&item->data, item_type_info, + item_transfer, direction); + } + + g_base_info_unref((GIBaseInfo *)item_type_info); + } + + if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) + || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { + if (type_tag == GI_TYPE_TAG_GLIST) { + g_list_free((GList *)list); + } else { + /* type_tag == GI_TYPE_TAG_GSLIST */ + g_slist_free(list); + } + } + + break; + } + case GI_TYPE_TAG_GHASH: + { + GHashTable *hash_table; + + g_assert(is_pointer); + + hash_table = arg->v_pointer; + + if (direction == GI_DIRECTION_IN && transfer != GI_TRANSFER_EVERYTHING) { + /* We created the table without a destroy function, so keys and + * values need to be released. */ + GITypeInfo *key_type_info; + GITypeInfo *value_type_info; + GITransfer item_transfer; + GHashTableIter hash_table_iter; + gpointer key; + gpointer value; + + key_type_info = g_type_info_get_param_type(type_info, 0); + g_assert(key_type_info != NULL); + + value_type_info = g_type_info_get_param_type(type_info, 1); + g_assert(value_type_info != NULL); + + if (direction == GI_DIRECTION_IN) { + item_transfer = GI_TRANSFER_NOTHING; + } else { + item_transfer = GI_TRANSFER_EVERYTHING; + } + + g_hash_table_iter_init(&hash_table_iter, hash_table); + while (g_hash_table_iter_next(&hash_table_iter, &key, &value)) { + _pygi_argument_release((GArgument *)&key, key_type_info, + item_transfer, direction); + _pygi_argument_release((GArgument *)&value, value_type_info, + item_transfer, direction); + } + + g_base_info_unref((GIBaseInfo *)key_type_info); + g_base_info_unref((GIBaseInfo *)value_type_info); + } else if (direction == GI_DIRECTION_OUT && transfer == GI_TRANSFER_CONTAINER) { + /* Be careful to avoid keys and values being freed if the + * callee gave a destroy function. */ + g_hash_table_steal_all(hash_table); + } + + if ((direction == GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING) + || (direction == GI_DIRECTION_OUT && transfer != GI_TRANSFER_NOTHING)) { + g_hash_table_unref(hash_table); + } + + break; + } + case GI_TYPE_TAG_ERROR: + { + GError *error; + + g_assert(is_pointer); + + error = *(GError **)arg->v_pointer; + + if (error != NULL) { + g_error_free(error); + } + + g_slice_free(GError *, arg->v_pointer); + break; + } + } +} + +void +_pygi_argument_init (void) +{ + PyDateTime_IMPORT; + _pygobject_import(); +} + diff --git a/gi/pygi-argument.h b/gi/pygi-argument.h new file mode 100644 index 00000000..59458fc3 --- /dev/null +++ b/gi/pygi-argument.h @@ -0,0 +1,65 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGI_ARGUMENT_H__ +#define __PYGI_ARGUMENT_H__ + +#include + +#include + +G_BEGIN_DECLS + + +/* Private */ + +gint _pygi_g_type_info_check_object (GITypeInfo *type_info, + gboolean may_be_null, + PyObject *object); + +gint _pygi_g_registered_type_info_check_object (GIRegisteredTypeInfo *info, + gboolean is_instance, + PyObject *object); + + +GArray* _pygi_argument_to_array (GArgument *arg, + GArgument *args[], + GITypeInfo *type_info); + +GArgument _pygi_argument_from_object (PyObject *object, + GITypeInfo *type_info, + GITransfer transfer); + +PyObject* _pygi_argument_to_object (GArgument *arg, + GITypeInfo *type_info, + GITransfer transfer); + + +void _pygi_argument_release (GArgument *arg, + GITypeInfo *type_info, + GITransfer transfer, + GIDirection direction); + +void _pygi_argument_init (void); + +G_END_DECLS + +#endif /* __PYGI_ARGUMENT_H__ */ diff --git a/gi/pygi-info.c b/gi/pygi-info.c new file mode 100644 index 00000000..5f4a174f --- /dev/null +++ b/gi/pygi-info.c @@ -0,0 +1,2093 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 Johan Dahlin + * + * pygi-info.c: GI.*Info wrappers. + * + * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "pygi-private.h" + +#include + +#define _PyGI_DEFINE_INFO_TYPE(name, cname, base) \ +static PyMethodDef _Py##cname##_methods[]; \ +PyTypeObject Py##cname##_Type = { \ + PyObject_HEAD_INIT(NULL) \ + 0, \ + "gi." name, /* tp_name */ \ + sizeof(PyGIBaseInfo), /* tp_basicsize */ \ + 0, /* tp_itemsize */ \ + (destructor)NULL, /* tp_dealloc */ \ + (printfunc)NULL, /* tp_print */ \ + (getattrfunc)NULL, /* tp_getattr */ \ + (setattrfunc)NULL, /* tp_setattr */ \ + (cmpfunc)NULL, /* tp_compare */ \ + (reprfunc)NULL, /* tp_repr */ \ + NULL, /* tp_as_number */ \ + NULL, /* tp_as_sequence */ \ + NULL, /* tp_as_mapping */ \ + (hashfunc)NULL, /* tp_hash */ \ + (ternaryfunc)NULL, /* tp_call */ \ + (reprfunc)NULL, /* tp_str */ \ + (getattrofunc)NULL, /* tp_getattro */ \ + (setattrofunc)NULL, /* tp_setattro */ \ + NULL, /* tp_as_buffer */ \ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ \ + NULL, /* tp_doc */ \ + (traverseproc)NULL, /* tp_traverse */ \ + (inquiry)NULL, /* tp_clear */ \ + (richcmpfunc)NULL, /* tp_richcompare */ \ + offsetof(PyGIBaseInfo, inst_weakreflist), /* tp_weaklistoffset */ \ + (getiterfunc)NULL, /* tp_iter */ \ + (iternextfunc)NULL, /* tp_iternext */ \ + _Py##cname##_methods, /* tp_methods */ \ + NULL, /* tp_members */ \ + NULL, /* tp_getset */ \ + &base /* tp_base */ \ +} + + +/* BaseInfo */ + +static void +_base_info_dealloc (PyGIBaseInfo *self) +{ + PyObject_GC_UnTrack((PyObject *)self); + + PyObject_ClearWeakRefs((PyObject *)self); + + g_base_info_unref(self->info); + + self->ob_type->tp_free((PyObject *)self); +} + +static int +_base_info_traverse (PyGIBaseInfo *self, + visitproc visit, + void *arg) +{ + return 0; +} + +static PyObject * +_base_info_repr (PyGIBaseInfo *self) +{ + return PyString_FromFormat("<%s object (%s) at 0x%p>", + self->ob_type->tp_name, g_base_info_get_name(self->info), (void *)self); +} + +static PyMethodDef _PyGIBaseInfo_methods[]; + +PyTypeObject PyGIBaseInfo_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "gi.BaseInfo", /* tp_name */ + sizeof(PyGIBaseInfo), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)_base_info_dealloc, /* tp_dealloc */ + (printfunc)NULL, /* tp_print */ + (getattrfunc)NULL, /* tp_getattr */ + (setattrfunc)NULL, /* tp_setattr */ + (cmpfunc)NULL, /* tp_compare */ + (reprfunc)_base_info_repr, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + (hashfunc)NULL, /* tp_hash */ + (ternaryfunc)NULL, /* tp_call */ + (reprfunc)NULL, /* tp_str */ + (getattrofunc)NULL, /* tp_getattro */ + (setattrofunc)NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE | + Py_TPFLAGS_HAVE_GC, /* tp_flags */ + NULL, /* tp_doc */ + (traverseproc)_base_info_traverse, /* tp_traverse */ + (inquiry)NULL, /* tp_clear */ + (richcmpfunc)NULL, /* tp_richcompare */ + offsetof(PyGIBaseInfo, inst_weakreflist), /* tp_weaklistoffset */ + (getiterfunc)NULL, /* tp_iter */ + (iternextfunc)NULL, /* tp_iternext */ + _PyGIBaseInfo_methods, /* tp_methods */ +}; + +static PyObject * +_wrap_g_base_info_get_name (PyGIBaseInfo *self) +{ + return PyString_FromString(g_base_info_get_name(self->info)); +} + +static PyObject * +_wrap_g_base_info_get_namespace (PyGIBaseInfo *self) +{ + return PyString_FromString(g_base_info_get_namespace(self->info)); +} + +static PyObject * +_wrap_g_base_info_get_container (PyGIBaseInfo *self) +{ + GIBaseInfo *info; + + info = g_base_info_get_container(self->info); + + if (info == NULL) { + Py_RETURN_NONE; + } + + return _pygi_info_new(info); +} + + +static PyMethodDef _PyGIBaseInfo_methods[] = { + { "get_name", (PyCFunction)_wrap_g_base_info_get_name, METH_NOARGS }, + { "get_namespace", (PyCFunction)_wrap_g_base_info_get_namespace, METH_NOARGS }, + { "get_container", (PyCFunction)_wrap_g_base_info_get_container, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +PyObject * +_pygi_info_new (GIBaseInfo *info) +{ + GIInfoType info_type; + PyTypeObject *type = NULL; + PyGIBaseInfo *self; + + info_type = g_base_info_get_type(info); + + switch (info_type) + { + case GI_INFO_TYPE_INVALID: + PyErr_SetString(PyExc_RuntimeError, "Invalid info type"); + return NULL; + case GI_INFO_TYPE_FUNCTION: + type = &PyGIFunctionInfo_Type; + break; + case GI_INFO_TYPE_CALLBACK: + PyErr_SetString(PyExc_NotImplementedError, "GICallbackInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_STRUCT: + type = &PyGIStructInfo_Type; + break; + case GI_INFO_TYPE_BOXED: + PyErr_SetString(PyExc_NotImplementedError, "GIBoxedInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + type = &PyGIEnumInfo_Type; + break; + case GI_INFO_TYPE_OBJECT: + type = &PyGIObjectInfo_Type; + break; + case GI_INFO_TYPE_INTERFACE: + type = &PyGIInterfaceInfo_Type; + break; + case GI_INFO_TYPE_CONSTANT: + type = &PyGIConstantInfo_Type; + break; + case GI_INFO_TYPE_ERROR_DOMAIN: + PyErr_SetString(PyExc_NotImplementedError, "GIErrorDomainInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_UNION: + PyErr_SetString(PyExc_NotImplementedError, "GIUnionInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_VALUE: + type = &PyGIValueInfo_Type; + break; + case GI_INFO_TYPE_SIGNAL: + PyErr_SetString(PyExc_NotImplementedError, "GISignalInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_VFUNC: + PyErr_SetString(PyExc_NotImplementedError, "GIVFuncInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_PROPERTY: + PyErr_SetString(PyExc_NotImplementedError, "GIPropertyInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_FIELD: + type = &PyGIFieldInfo_Type; + break; + case GI_INFO_TYPE_ARG: + PyErr_SetString(PyExc_NotImplementedError, "GIArgInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_TYPE: + PyErr_SetString(PyExc_NotImplementedError, "GITypeInfo bindings not implemented"); + return NULL; + case GI_INFO_TYPE_UNRESOLVED: + type = &PyGIUnresolvedInfo_Type; + break; + } + + self = (PyGIBaseInfo *)type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + + self->info = g_base_info_ref(info); + + return (PyObject *)self; +} + +GIBaseInfo * +_pygi_object_get_gi_info (PyObject *object, + PyTypeObject *type) +{ + PyObject *py_info; + GIBaseInfo *info = NULL; + + py_info = PyObject_GetAttrString(object, "__info__"); + if (py_info == NULL) { + return NULL; + } + if (!PyObject_TypeCheck(py_info, type)) { + PyErr_Format(PyExc_TypeError, "attribute '__info__' must be %s, not %s", + type->tp_name, py_info->ob_type->tp_name); + goto out; + } + + info = ((PyGIBaseInfo *)py_info)->info; + g_base_info_ref(info); + +out: + Py_DECREF(py_info); + + return info; +} + + +/* CallableInfo */ +_PyGI_DEFINE_INFO_TYPE("CallableInfo", GICallableInfo, PyGIBaseInfo_Type); + +static PyMethodDef _PyGICallableInfo_methods[] = { + { NULL, NULL, 0 } +}; + + +/* FunctionInfo */ +_PyGI_DEFINE_INFO_TYPE("FunctionInfo", GIFunctionInfo, PyGICallableInfo_Type); + +static PyObject * +_wrap_g_function_info_is_constructor (PyGIBaseInfo *self) +{ + GIFunctionInfoFlags flags; + gboolean is_constructor; + + flags = g_function_info_get_flags((GIFunctionInfo*)self->info); + is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR; + + return PyBool_FromLong(is_constructor); +} + +static PyObject * +_wrap_g_function_info_is_method (PyGIBaseInfo *self) +{ + GIFunctionInfoFlags flags; + gboolean is_method; + + flags = g_function_info_get_flags((GIFunctionInfo*)self->info); + is_method = flags & GI_FUNCTION_IS_METHOD; + + return PyBool_FromLong(is_method); +} + +gsize +_pygi_g_type_tag_size (GITypeTag type_tag) +{ + gsize size = 0; + + switch(type_tag) { + case GI_TYPE_TAG_BOOLEAN: + size = sizeof(gboolean); + break; + case GI_TYPE_TAG_INT8: + case GI_TYPE_TAG_UINT8: + size = sizeof(gint8); + break; + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_UINT16: + size = sizeof(gint16); + break; + case GI_TYPE_TAG_INT32: + case GI_TYPE_TAG_UINT32: + size = sizeof(gint32); + break; + case GI_TYPE_TAG_INT64: + case GI_TYPE_TAG_UINT64: + size = sizeof(gint64); + break; + case GI_TYPE_TAG_SHORT: + case GI_TYPE_TAG_USHORT: + size = sizeof(gshort); + break; + case GI_TYPE_TAG_INT: + case GI_TYPE_TAG_UINT: + size = sizeof(gint); + break; + case GI_TYPE_TAG_LONG: + case GI_TYPE_TAG_ULONG: + size = sizeof(glong); + break; + case GI_TYPE_TAG_SIZE: + case GI_TYPE_TAG_SSIZE: + size = sizeof(gsize); + break; + case GI_TYPE_TAG_FLOAT: + size = sizeof(gfloat); + break; + case GI_TYPE_TAG_DOUBLE: + size = sizeof(gdouble); + break; + case GI_TYPE_TAG_TIME_T: + size = sizeof(time_t); + break; + case GI_TYPE_TAG_GTYPE: + size = sizeof(GType); + break; + case GI_TYPE_TAG_VOID: + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + case GI_TYPE_TAG_ARRAY: + case GI_TYPE_TAG_INTERFACE: + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + case GI_TYPE_TAG_GHASH: + case GI_TYPE_TAG_ERROR: + PyErr_Format(PyExc_TypeError, + "Unable to know the size (assuming %s is not a pointer)", + g_type_tag_to_string(type_tag)); + break; + } + + return size; +} + +gsize +_pygi_g_type_info_size (GITypeInfo *type_info) +{ + gsize size = 0; + gboolean is_pointer; + + is_pointer = g_type_info_is_pointer(type_info); + + if (is_pointer) { + size = sizeof(gpointer); + } else { + GITypeTag type_tag; + + type_tag = g_type_info_get_tag(type_info); + switch(type_tag) { + case GI_TYPE_TAG_BOOLEAN: + case GI_TYPE_TAG_INT8: + case GI_TYPE_TAG_UINT8: + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_UINT16: + case GI_TYPE_TAG_INT32: + case GI_TYPE_TAG_UINT32: + case GI_TYPE_TAG_INT64: + case GI_TYPE_TAG_UINT64: + case GI_TYPE_TAG_SHORT: + case GI_TYPE_TAG_USHORT: + case GI_TYPE_TAG_INT: + case GI_TYPE_TAG_UINT: + case GI_TYPE_TAG_LONG: + case GI_TYPE_TAG_ULONG: + case GI_TYPE_TAG_SIZE: + case GI_TYPE_TAG_SSIZE: + case GI_TYPE_TAG_FLOAT: + case GI_TYPE_TAG_DOUBLE: + case GI_TYPE_TAG_TIME_T: + case GI_TYPE_TAG_GTYPE: + size = _pygi_g_type_tag_size(type_tag); + g_assert(size > 0); + break; + case GI_TYPE_TAG_INTERFACE: + { + GIBaseInfo *info; + GIInfoType info_type; + + info = g_type_info_get_interface(type_info); + info_type = g_base_info_get_type(info); + + switch (info_type) { + case GI_INFO_TYPE_STRUCT: + size = g_struct_info_get_size((GIStructInfo *)info); + break; + case GI_INFO_TYPE_UNION: + size = g_union_info_get_size((GIUnionInfo *)info); + break; + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + { + GITypeTag type_tag; + + type_tag = g_enum_info_get_storage_type((GIEnumInfo *)info); + size = _pygi_g_type_tag_size(type_tag); + break; + } + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_OBJECT: + case GI_INFO_TYPE_INTERFACE: + case GI_INFO_TYPE_CALLBACK: + /* Should have been catched by is_pointer above. */ + case GI_INFO_TYPE_VFUNC: + case GI_INFO_TYPE_INVALID: + case GI_INFO_TYPE_FUNCTION: + case GI_INFO_TYPE_CONSTANT: + case GI_INFO_TYPE_ERROR_DOMAIN: + case GI_INFO_TYPE_VALUE: + case GI_INFO_TYPE_SIGNAL: + case GI_INFO_TYPE_PROPERTY: + case GI_INFO_TYPE_FIELD: + case GI_INFO_TYPE_ARG: + case GI_INFO_TYPE_TYPE: + case GI_INFO_TYPE_UNRESOLVED: + g_assert_not_reached(); + break; + } + + g_base_info_unref(info); + break; + } + case GI_TYPE_TAG_ARRAY: + case GI_TYPE_TAG_VOID: + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + case GI_TYPE_TAG_GHASH: + case GI_TYPE_TAG_ERROR: + /* Should have been catched by is_pointer above. */ + g_assert_not_reached(); + break; + } + } + + return size; +} + + +static PyObject * +_wrap_g_function_info_invoke (PyGIBaseInfo *self, + PyObject *py_args) +{ + gboolean is_method; + gboolean is_constructor; + + gsize n_args; + gsize n_in_args; + gsize n_out_args; + gsize n_backup_args; + Py_ssize_t n_py_args; + gsize n_aux_in_args; + gsize n_aux_out_args; + gsize n_return_values; + + glong error_arg_pos; + + GIArgInfo **arg_infos; + GITypeInfo **arg_type_infos; + GITypeInfo *return_type_info; + GITypeTag return_type_tag; + + GArgument **args; + gboolean *args_is_auxiliary; + + GArgument *in_args; + GArgument *out_args; + GArgument *out_values; + GArgument *backup_args; + GArgument return_arg; + + PyObject *return_value = NULL; + + gsize i; + + { + GIFunctionInfoFlags flags; + + flags = g_function_info_get_flags((GIFunctionInfo *)self->info); + is_method = (flags & GI_FUNCTION_IS_METHOD) != 0; + is_constructor = (flags & GI_FUNCTION_IS_CONSTRUCTOR) != 0; + } + + /* Count arguments. */ + n_args = g_callable_info_get_n_args((GICallableInfo *)self->info); + n_in_args = 0; + n_out_args = 0; + n_backup_args = 0; + n_aux_in_args = 0; + n_aux_out_args = 0; + + error_arg_pos = -1; + + arg_infos = g_newa(GIArgInfo *, n_args); + arg_type_infos = g_newa(GITypeInfo *, n_args); + + args_is_auxiliary = g_newa(gboolean, n_args); + memset(args_is_auxiliary, 0, sizeof(args_is_auxiliary) * n_args); + + if (is_method) { + /* The first argument is the instance. */ + n_in_args += 1; + } + + for (i = 0; i < n_args; i++) { + GIDirection direction; + GITransfer transfer; + GITypeTag arg_type_tag; + + arg_infos[i] = g_callable_info_get_arg((GICallableInfo *)self->info, i); + arg_type_infos[i] = g_arg_info_get_type(arg_infos[i]); + + direction = g_arg_info_get_direction(arg_infos[i]); + transfer = g_arg_info_get_ownership_transfer(arg_infos[i]); + arg_type_tag = g_type_info_get_tag(arg_type_infos[i]); + + if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { + n_in_args += 1; + if (transfer == GI_TRANSFER_CONTAINER) { + n_backup_args += 1; + } + } + if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { + n_out_args += 1; + } + + if (direction == GI_DIRECTION_INOUT && transfer == GI_TRANSFER_NOTHING) { + n_backup_args += 1; + } + + switch (arg_type_tag) { + case GI_TYPE_TAG_ARRAY: + { + gint length_arg_pos; + + length_arg_pos = g_type_info_get_array_length(arg_type_infos[i]); + if (length_arg_pos < 0) { + break; + } + + g_assert(length_arg_pos < n_args); + args_is_auxiliary[length_arg_pos] = TRUE; + + if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { + n_aux_in_args += 1; + } + if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) { + n_aux_out_args += 1; + } + + break; + } + case GI_TYPE_TAG_ERROR: + g_warn_if_fail(error_arg_pos < 0); + error_arg_pos = i; + break; + default: + break; + } + } + + return_type_info = g_callable_info_get_return_type((GICallableInfo *)self->info); + return_type_tag = g_type_info_get_tag(return_type_info); + + if (return_type_tag == GI_TYPE_TAG_ARRAY) { + gint length_arg_pos; + length_arg_pos = g_type_info_get_array_length(return_type_info); + if (length_arg_pos >= 0) { + g_assert(length_arg_pos < n_args); + args_is_auxiliary[length_arg_pos] = TRUE; + n_aux_out_args += 1; + } + } + + n_return_values = n_out_args - n_aux_out_args; + if (return_type_tag != GI_TYPE_TAG_VOID) { + n_return_values += 1; + } + + { + gsize n_py_args_expected; + Py_ssize_t py_args_pos; + + /* Check the argument count. */ + n_py_args = PyTuple_Size(py_args); + g_assert(n_py_args >= 0); + + n_py_args_expected = n_in_args + + (is_constructor ? 1 : 0) + - n_aux_in_args + - (error_arg_pos >= 0 ? 1 : 0); + + if (n_py_args != n_py_args_expected) { + PyErr_Format(PyExc_TypeError, + "takes exactly %zd argument(s) (%zd given)", + n_py_args_expected, n_py_args); + goto out; + } + + /* Check argument types. */ + py_args_pos = 0; + if (is_constructor || is_method) { + py_args_pos += 1; + } + + for (i = 0; i < n_args; i++) { + GIDirection direction; + GITypeTag type_tag; + gboolean may_be_null; + PyObject *py_arg; + gint retval; + + direction = g_arg_info_get_direction(arg_infos[i]); + type_tag = g_type_info_get_tag(arg_type_infos[i]); + + if (direction == GI_DIRECTION_OUT + || args_is_auxiliary[i] + || type_tag == GI_TYPE_TAG_ERROR) { + continue; + } + + g_assert(py_args_pos < n_py_args); + py_arg = PyTuple_GET_ITEM(py_args, py_args_pos); + + may_be_null = g_arg_info_may_be_null(arg_infos[i]); + + retval = _pygi_g_type_info_check_object(arg_type_infos[i], + may_be_null, py_arg); + + if (retval < 0) { + goto out; + } else if (!retval) { + _PyGI_ERROR_PREFIX("argument %zd: ", py_args_pos); + goto out; + } + + py_args_pos += 1; + } + + g_assert(py_args_pos == n_py_args); + } + + args = g_newa(GArgument *, n_args); + in_args = g_newa(GArgument, n_in_args); + out_args = g_newa(GArgument, n_out_args); + out_values = g_newa(GArgument, n_out_args); + backup_args = g_newa(GArgument, n_backup_args); + + /* Bind args so we can use an unique index. */ + { + gsize in_args_pos; + gsize out_args_pos; + + in_args_pos = is_method ? 1 : 0; + out_args_pos = 0; + + for (i = 0; i < n_args; i++) { + GIDirection direction; + + direction = g_arg_info_get_direction(arg_infos[i]); + + switch (direction) { + case GI_DIRECTION_IN: + g_assert(in_args_pos < n_in_args); + args[i] = &in_args[in_args_pos]; + in_args_pos += 1; + break; + case GI_DIRECTION_INOUT: + g_assert(in_args_pos < n_in_args); + g_assert(out_args_pos < n_out_args); + in_args[in_args_pos].v_pointer = &out_values[out_args_pos]; + in_args_pos += 1; + case GI_DIRECTION_OUT: + g_assert(out_args_pos < n_out_args); + out_args[out_args_pos].v_pointer = &out_values[out_args_pos]; + args[i] = &out_values[out_args_pos]; + out_args_pos += 1; + } + } + + g_assert(in_args_pos == n_in_args); + g_assert(out_args_pos == n_out_args); + } + + /* Convert the input arguments. */ + { + Py_ssize_t py_args_pos; + gsize backup_args_pos; + + py_args_pos = 0; + backup_args_pos = 0; + + if (is_constructor) { + /* Skip the first argument. */ + py_args_pos += 1; + } else if (is_method) { + /* Get the instance. */ + GIBaseInfo *container_info; + GIInfoType container_info_type; + PyObject *py_arg; + + container_info = g_base_info_get_container(self->info); + container_info_type = g_base_info_get_type(container_info); + + g_assert(py_args_pos < n_py_args); + py_arg = PyTuple_GET_ITEM(py_args, py_args_pos); + + switch(container_info_type) { + case GI_INFO_TYPE_UNION: + PyErr_SetString(PyExc_NotImplementedError, "calling methods on unions is not supported yet."); + goto out; + break; + case GI_INFO_TYPE_STRUCT: + { + GType type; + + type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)container_info); + + if (g_type_is_a(type, G_TYPE_BOXED)) { + g_assert(n_in_args > 0); + in_args[0].v_pointer = pyg_boxed_get(py_arg, void); + } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) { + g_assert(n_in_args > 0); + in_args[0].v_pointer = pyg_pointer_get(py_arg, void); + } else { + PyErr_Format(PyExc_TypeError, "unable to convert an instance of '%s'", g_type_name(type)); + goto out; + } + + break; + } + case GI_INFO_TYPE_OBJECT: + case GI_INFO_TYPE_INTERFACE: + g_assert(n_in_args > 0); + in_args[0].v_pointer = pygobject_get(py_arg); + break; + default: + /* Other types don't have methods. */ + g_assert_not_reached(); + } + + py_args_pos += 1; + } + + for (i = 0; i < n_args; i++) { + GIDirection direction; + + if (args_is_auxiliary[i]) { + continue; + } + + direction = g_arg_info_get_direction(arg_infos[i]); + + if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) { + PyObject *py_arg; + GITypeTag arg_type_tag; + GITransfer transfer; + + arg_type_tag = g_type_info_get_tag(arg_type_infos[i]); + + if (arg_type_tag == GI_TYPE_TAG_ERROR) { + GError **error; + + error = g_slice_new(GError *); + *error = NULL; + + args[i]->v_pointer = error; + continue; + } + + transfer = g_arg_info_get_ownership_transfer(arg_infos[i]); + + g_assert(py_args_pos < n_py_args); + py_arg = PyTuple_GET_ITEM(py_args, py_args_pos); + + *args[i] = _pygi_argument_from_object(py_arg, arg_type_infos[i], transfer); + + if (PyErr_Occurred()) { + /* TODO: release previous input arguments. */ + goto out; + } + + if (direction == GI_DIRECTION_INOUT && transfer == GI_TRANSFER_NOTHING) { + /* We need to keep a copy of the argument to be able to release it later. */ + g_assert(backup_args_pos < n_backup_args); + backup_args[backup_args_pos] = *args[i]; + backup_args_pos += 1; + } else if (transfer == GI_TRANSFER_CONTAINER) { + /* We need to keep a copy of the items to be able to release them later. */ + switch (arg_type_tag) { + case GI_TYPE_TAG_ARRAY: + { + GArray *array; + gsize item_size; + GArray *new_array; + + array = args[i]->v_pointer; + + item_size = g_array_get_element_size(array); + + new_array = g_array_sized_new(FALSE, FALSE, item_size, array->len); + g_array_append_vals(new_array, array->data, array->len); + + g_assert(backup_args_pos < n_backup_args); + backup_args[backup_args_pos].v_pointer = new_array; + + break; + } + case GI_TYPE_TAG_GLIST: + g_assert(backup_args_pos < n_backup_args); + backup_args[backup_args_pos].v_pointer = g_list_copy(args[i]->v_pointer); + break; + case GI_TYPE_TAG_GSLIST: + g_assert(backup_args_pos < n_backup_args); + backup_args[backup_args_pos].v_pointer = g_slist_copy(args[i]->v_pointer); + break; + case GI_TYPE_TAG_GHASH: + { + GHashTable *hash_table; + GList *keys; + GList *values; + + hash_table = args[i]->v_pointer; + + keys = g_hash_table_get_keys(hash_table); + values = g_hash_table_get_values(hash_table); + + g_assert(backup_args_pos < n_backup_args); + backup_args[backup_args_pos].v_pointer = g_list_concat(keys, values); + + break; + } + default: + g_warn_if_reached(); + } + + backup_args_pos += 1; + } + + if (arg_type_tag == GI_TYPE_TAG_ARRAY) { + GArray *array; + gssize length_arg_pos; + + array = args[i]->v_pointer; + + length_arg_pos = g_type_info_get_array_length(arg_type_infos[i]); + if (length_arg_pos >= 0) { + /* Set the auxiliary argument holding the length. */ + args[length_arg_pos]->v_size = array->len; + } + + /* Get rid of the GArray. */ + args[i]->v_pointer = array->data; + + if (direction != GI_DIRECTION_INOUT || transfer != GI_TRANSFER_NOTHING) { + /* The array hasn't been referenced anywhere, so free it to avoid losing memory. */ + g_array_free(array, FALSE); + } + } + + py_args_pos += 1; + } + } + + g_assert(py_args_pos == n_py_args); + g_assert(backup_args_pos == n_backup_args); + } + + /* Invoke the callable. */ + { + GError *error; + gint retval; + + error = NULL; + + retval = g_function_info_invoke((GIFunctionInfo *)self->info, + in_args, n_in_args, out_args, n_out_args, &return_arg, &error); + if (!retval) { + g_assert(error != NULL); + /* TODO: raise the right error, out of the error domain. */ + PyErr_SetString(PyExc_RuntimeError, error->message); + g_error_free(error); + + /* TODO: release input arguments. */ + + goto out; + } + } + + if (error_arg_pos >= 0) { + GError **error; + + error = args[error_arg_pos]->v_pointer; + + if (*error != NULL) { + /* TODO: raise the right error, out of the error domain, if applicable. */ + PyErr_SetString(PyExc_Exception, (*error)->message); + g_error_free(*error); + + /* TODO: release input arguments. */ + + goto out; + } + } + + /* Convert the return value. */ + if (is_constructor) { + PyTypeObject *py_type; + GIBaseInfo *info; + GIInfoType info_type; + GITransfer transfer; + + g_assert(n_py_args > 0); + py_type = (PyTypeObject *)PyTuple_GET_ITEM(py_args, 0); + + info = g_type_info_get_interface(return_type_info); + g_assert(info != NULL); + + info_type = g_base_info_get_type(info); + + transfer = g_callable_info_get_caller_owns((GICallableInfo *)self->info); + + switch (info_type) { + case GI_INFO_TYPE_UNION: + /* TODO */ + PyErr_SetString(PyExc_NotImplementedError, "creating unions is not supported yet"); + g_base_info_unref(info); + goto out; + case GI_INFO_TYPE_STRUCT: + { + GType type; + + type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)info); + + if (g_type_is_a(type, G_TYPE_BOXED)) { + if (return_arg.v_pointer == NULL) { + PyErr_SetString(PyExc_TypeError, "constructor returned NULL"); + break; + } + g_warn_if_fail(transfer == GI_TRANSFER_EVERYTHING); + return_value = pyg_boxed_new(type, return_arg.v_pointer, FALSE, transfer == GI_TRANSFER_EVERYTHING); + } else if (g_type_is_a(type, G_TYPE_POINTER) || type == G_TYPE_NONE) { + if (return_arg.v_pointer == NULL) { + PyErr_SetString(PyExc_TypeError, "constructor returned NULL"); + break; + } + g_warn_if_fail(transfer == GI_TRANSFER_NOTHING); + return_value = _pygi_struct_new(py_type, return_arg.v_pointer, transfer == GI_TRANSFER_EVERYTHING); + } else { + PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", py_type->tp_name); + g_base_info_unref(info); + goto out; + } + + break; + } + case GI_INFO_TYPE_OBJECT: + if (return_arg.v_pointer == NULL) { + PyErr_SetString(PyExc_TypeError, "constructor returned NULL"); + break; + } + return_value = pygobject_new(return_arg.v_pointer); + if (transfer == GI_TRANSFER_EVERYTHING) { + /* The new wrapper increased the reference count, so decrease it. */ + g_object_unref (return_arg.v_pointer); + } + break; + default: + /* Other types don't have neither methods nor constructors. */ + g_assert_not_reached(); + } + + g_base_info_unref(info); + + if (return_value == NULL) { + /* TODO: release arguments. */ + goto out; + } + } else { + GITransfer transfer; + + if (return_type_tag == GI_TYPE_TAG_ARRAY) { + /* Create a #GArray. */ + return_arg.v_pointer = _pygi_argument_to_array(&return_arg, args, return_type_info); + } + + transfer = g_callable_info_get_caller_owns((GICallableInfo *)self->info); + + return_value = _pygi_argument_to_object(&return_arg, return_type_info, transfer); + if (return_value == NULL) { + /* TODO: release argument. */ + goto out; + } + + _pygi_argument_release(&return_arg, return_type_info, transfer, GI_DIRECTION_OUT); + + if (return_type_tag == GI_TYPE_TAG_ARRAY + && transfer == GI_TRANSFER_NOTHING) { + /* We created a #GArray, so free it. */ + return_arg.v_pointer = g_array_free(return_arg.v_pointer, FALSE); + } + } + + /* Convert output arguments and release arguments. */ + { + gsize backup_args_pos; + gsize return_values_pos; + + backup_args_pos = 0; + return_values_pos = 0; + + if (n_return_values > 1) { + /* Return a tuple. */ + PyObject *return_values; + + return_values = PyTuple_New(n_return_values); + if (return_values == NULL) { + /* TODO: release arguments. */ + goto out; + } + + if (return_type_tag == GI_TYPE_TAG_VOID) { + /* The current return value is None. */ + Py_DECREF(return_value); + } else { + /* Put the return value first. */ + g_assert(return_value != NULL); + PyTuple_SET_ITEM(return_values, return_values_pos, return_value); + return_values_pos += 1; + } + + return_value = return_values; + } + + for (i = 0; i < n_args; i++) { + GIDirection direction; + GITypeTag type_tag; + GITransfer transfer; + + if (args_is_auxiliary[i]) { + /* Auxiliary arguments are handled at the same time as their relatives. */ + continue; + } + + direction = g_arg_info_get_direction(arg_infos[i]); + transfer = g_arg_info_get_ownership_transfer(arg_infos[i]); + + type_tag = g_type_info_get_tag(arg_type_infos[i]); + + if (type_tag == GI_TYPE_TAG_ARRAY + && (direction != GI_DIRECTION_IN || transfer == GI_TRANSFER_NOTHING)) { + /* Create a #GArray. */ + args[i]->v_pointer = _pygi_argument_to_array(args[i], args, arg_type_infos[i]); + } + + if (direction == GI_DIRECTION_INOUT || direction == GI_DIRECTION_OUT) { + /* Convert the argument. */ + PyObject *obj; + + obj = _pygi_argument_to_object(args[i], arg_type_infos[i], transfer); + if (obj == NULL) { + /* TODO: release arguments. */ + goto out; + } + + g_assert(return_values_pos < n_return_values); + + if (n_return_values > 1) { + PyTuple_SET_ITEM(return_value, return_values_pos, obj); + } else { + /* The current return value is None. */ + Py_DECREF(return_value); + return_value = obj; + } + + return_values_pos += 1; + } + + /* Release the argument. */ + + if ((direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) + && transfer == GI_TRANSFER_CONTAINER) { + /* Release the items we kept in another container. */ + switch (type_tag) { + case GI_TYPE_TAG_ARRAY: + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + g_assert(backup_args_pos < n_backup_args); + _pygi_argument_release(&backup_args[backup_args_pos], arg_type_infos[i], + transfer, GI_DIRECTION_IN); + break; + case GI_TYPE_TAG_GHASH: + { + GITypeInfo *key_type_info; + GITypeInfo *value_type_info; + GList *item; + gsize length; + gsize j; + + key_type_info = g_type_info_get_param_type(arg_type_infos[i], 0); + value_type_info = g_type_info_get_param_type(arg_type_infos[i], 1); + + g_assert(backup_args_pos < n_backup_args); + item = backup_args[backup_args_pos].v_pointer; + + length = g_list_length(item) / 2; + + for (j = 0; j < length; j++, item = g_list_next(item)) { + _pygi_argument_release((GArgument *)&item->data, key_type_info, + GI_TRANSFER_NOTHING, GI_DIRECTION_IN); + } + + for (j = 0; j < length; j++, item = g_list_next(item)) { + _pygi_argument_release((GArgument *)&item->data, value_type_info, + GI_TRANSFER_NOTHING, GI_DIRECTION_IN); + } + + g_list_free(backup_args[backup_args_pos].v_pointer); + + break; + } + default: + g_warn_if_reached(); + } + + if (direction == GI_DIRECTION_INOUT) { + /* Release the output argument. */ + _pygi_argument_release(args[i], arg_type_infos[i], GI_TRANSFER_CONTAINER, + GI_DIRECTION_OUT); + } + + backup_args_pos += 1; + } else if (direction == GI_DIRECTION_INOUT) { + if (transfer == GI_TRANSFER_NOTHING) { + g_assert(backup_args_pos < n_backup_args); + _pygi_argument_release(&backup_args[backup_args_pos], arg_type_infos[i], + GI_TRANSFER_NOTHING, GI_DIRECTION_IN); + backup_args_pos += 1; + } + + _pygi_argument_release(args[i], arg_type_infos[i], transfer, + GI_DIRECTION_OUT); + } else { + _pygi_argument_release(args[i], arg_type_infos[i], transfer, direction); + } + + if (type_tag == GI_TYPE_TAG_ARRAY + && (direction != GI_DIRECTION_IN && transfer == GI_TRANSFER_NOTHING)) { + /* We created a #GArray and it has not been released above, so free it. */ + args[i]->v_pointer = g_array_free(args[i]->v_pointer, FALSE); + } + } + + g_assert(n_return_values <= 1 || return_values_pos == n_return_values); + g_assert(backup_args_pos == n_backup_args); + } + +out: + g_base_info_unref((GIBaseInfo *)return_type_info); + + for (i = 0; i < n_args; i++) { + g_base_info_unref((GIBaseInfo *)arg_type_infos[i]); + g_base_info_unref((GIBaseInfo *)arg_infos[i]); + } + + if (PyErr_Occurred()) { + Py_CLEAR(return_value); + } + + return return_value; +} + +static PyMethodDef _PyGIFunctionInfo_methods[] = { + { "is_constructor", (PyCFunction)_wrap_g_function_info_is_constructor, METH_NOARGS }, + { "is_method", (PyCFunction)_wrap_g_function_info_is_method, METH_NOARGS }, + { "invoke", (PyCFunction)_wrap_g_function_info_invoke, METH_VARARGS }, + { NULL, NULL, 0 } +}; + + +/* RegisteredTypeInfo */ +_PyGI_DEFINE_INFO_TYPE("RegisteredTypeInfo", GIRegisteredTypeInfo, PyGIBaseInfo_Type); + +static PyObject * +_wrap_g_registered_type_info_get_g_type (PyGIBaseInfo *self) +{ + GType type; + + type = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *)self->info); + + return pyg_type_wrapper_new(type); +} + +static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = { + { "get_g_type", (PyCFunction)_wrap_g_registered_type_info_get_g_type, METH_NOARGS }, + { NULL, NULL, 0 } +}; + + +/* GIStructInfo */ +_PyGI_DEFINE_INFO_TYPE("StructInfo", GIStructInfo, PyGIRegisteredTypeInfo_Type); + +static PyObject * +_wrap_g_struct_info_get_fields (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_struct_info_get_n_fields((GIStructInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_struct_info_get_field((GIStructInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyObject * +_wrap_g_struct_info_get_methods (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_struct_info_get_n_methods((GIStructInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_struct_info_get_method((GIStructInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyMethodDef _PyGIStructInfo_methods[] = { + { "get_fields", (PyCFunction)_wrap_g_struct_info_get_fields, METH_NOARGS }, + { "get_methods", (PyCFunction)_wrap_g_struct_info_get_methods, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +gboolean +pygi_g_struct_info_is_simple (GIStructInfo *struct_info) +{ + gboolean is_simple; + gsize n_field_infos; + gsize i; + + is_simple = TRUE; + + n_field_infos = g_struct_info_get_n_fields(struct_info); + + for (i = 0; i < n_field_infos && is_simple; i++) { + GIFieldInfo *field_info; + GITypeInfo *field_type_info; + gboolean is_pointer; + + field_info = g_struct_info_get_field(struct_info, i); + field_type_info = g_field_info_get_type(field_info); + is_pointer = g_type_info_is_pointer(field_type_info); + + if (is_pointer) { + is_simple = FALSE; + } else { + GITypeTag field_type_tag; + + field_type_tag = g_type_info_get_tag(field_type_info); + + switch (field_type_tag) { + case GI_TYPE_TAG_BOOLEAN: + case GI_TYPE_TAG_INT8: + case GI_TYPE_TAG_UINT8: + case GI_TYPE_TAG_INT16: + case GI_TYPE_TAG_UINT16: + case GI_TYPE_TAG_INT32: + case GI_TYPE_TAG_UINT32: + case GI_TYPE_TAG_SHORT: + case GI_TYPE_TAG_USHORT: + case GI_TYPE_TAG_INT: + case GI_TYPE_TAG_UINT: + case GI_TYPE_TAG_INT64: + case GI_TYPE_TAG_UINT64: + case GI_TYPE_TAG_LONG: + case GI_TYPE_TAG_ULONG: + case GI_TYPE_TAG_SSIZE: + case GI_TYPE_TAG_SIZE: + case GI_TYPE_TAG_FLOAT: + case GI_TYPE_TAG_DOUBLE: + case GI_TYPE_TAG_TIME_T: + break; + case GI_TYPE_TAG_VOID: + case GI_TYPE_TAG_GTYPE: + case GI_TYPE_TAG_ERROR: + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + case GI_TYPE_TAG_ARRAY: + case GI_TYPE_TAG_GLIST: + case GI_TYPE_TAG_GSLIST: + case GI_TYPE_TAG_GHASH: + /* Should have been catched by is_pointer above. */ + g_assert_not_reached(); + break; + case GI_TYPE_TAG_INTERFACE: + { + GIBaseInfo *info; + GIInfoType info_type; + + info = g_type_info_get_interface(field_type_info); + info_type = g_base_info_get_type(info); + + switch (info_type) { + case GI_INFO_TYPE_BOXED: + case GI_INFO_TYPE_STRUCT: + is_simple = pygi_g_struct_info_is_simple((GIStructInfo *)info); + break; + case GI_INFO_TYPE_UNION: + /* TODO */ + is_simple = FALSE; + break; + case GI_INFO_TYPE_ENUM: + case GI_INFO_TYPE_FLAGS: + break; + case GI_INFO_TYPE_OBJECT: + case GI_INFO_TYPE_VFUNC: + case GI_INFO_TYPE_CALLBACK: + case GI_INFO_TYPE_INVALID: + case GI_INFO_TYPE_INTERFACE: + case GI_INFO_TYPE_FUNCTION: + case GI_INFO_TYPE_CONSTANT: + case GI_INFO_TYPE_ERROR_DOMAIN: + case GI_INFO_TYPE_VALUE: + case GI_INFO_TYPE_SIGNAL: + case GI_INFO_TYPE_PROPERTY: + case GI_INFO_TYPE_FIELD: + case GI_INFO_TYPE_ARG: + case GI_INFO_TYPE_TYPE: + case GI_INFO_TYPE_UNRESOLVED: + is_simple = FALSE; + break; + } + + g_base_info_unref(info); + break; + } + } + } + + g_base_info_unref((GIBaseInfo *)field_type_info); + g_base_info_unref((GIBaseInfo *)field_info); + } + + return is_simple; +} + + +/* EnumInfo */ +_PyGI_DEFINE_INFO_TYPE("EnumInfo", GIEnumInfo, PyGIRegisteredTypeInfo_Type); + +static PyObject * +_wrap_g_enum_info_get_values (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_enum_info_get_n_values((GIEnumInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_enum_info_get_value((GIEnumInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyMethodDef _PyGIEnumInfo_methods[] = { + { "get_values", (PyCFunction)_wrap_g_enum_info_get_values, METH_NOARGS }, + { NULL, NULL, 0 } +}; + + +/* ObjectInfo */ +_PyGI_DEFINE_INFO_TYPE("ObjectInfo", GIObjectInfo, PyGIRegisteredTypeInfo_Type); + +static PyObject * +_wrap_g_object_info_get_parent (PyGIBaseInfo *self) +{ + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_object_info_get_parent((GIObjectInfo*)self->info); + + if (info == NULL) { + Py_RETURN_NONE; + } + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + return py_info; +} + +static PyObject * +_wrap_g_object_info_get_methods (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_object_info_get_n_methods((GIObjectInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_object_info_get_method((GIObjectInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyObject * +_wrap_g_object_info_get_fields (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_object_info_get_n_fields((GIObjectInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_object_info_get_field((GIObjectInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyObject * +_wrap_g_object_info_get_interfaces (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_object_info_get_n_interfaces((GIObjectInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_object_info_get_interface((GIObjectInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyObject * +_wrap_g_object_info_get_constants (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_object_info_get_n_constants((GIObjectInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_object_info_get_constant((GIObjectInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyMethodDef _PyGIObjectInfo_methods[] = { + { "get_parent", (PyCFunction)_wrap_g_object_info_get_parent, METH_NOARGS }, + { "get_methods", (PyCFunction)_wrap_g_object_info_get_methods, METH_NOARGS }, + { "get_fields", (PyCFunction)_wrap_g_object_info_get_fields, METH_NOARGS }, + { "get_interfaces", (PyCFunction)_wrap_g_object_info_get_interfaces, METH_NOARGS }, + { "get_constants", (PyCFunction)_wrap_g_object_info_get_constants, METH_NOARGS }, + { NULL, NULL, 0 } +}; + + +/* GIInterfaceInfo */ +_PyGI_DEFINE_INFO_TYPE("InterfaceInfo", GIInterfaceInfo, PyGIRegisteredTypeInfo_Type); + +static PyObject * +_wrap_g_interface_info_get_methods (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_interface_info_get_n_methods((GIInterfaceInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_interface_info_get_method((GIInterfaceInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyObject * +_wrap_g_interface_info_get_constants (PyGIBaseInfo *self) +{ + gssize n_infos; + PyObject *infos; + gssize i; + + n_infos = g_interface_info_get_n_constants((GIInterfaceInfo *)self->info); + + infos = PyTuple_New(n_infos); + if (infos == NULL) { + return NULL; + } + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = (GIBaseInfo *)g_interface_info_get_constant((GIInterfaceInfo *)self->info, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyMethodDef _PyGIInterfaceInfo_methods[] = { + { "get_methods", (PyCFunction)_wrap_g_interface_info_get_methods, METH_NOARGS }, + { "get_constants", (PyCFunction)_wrap_g_interface_info_get_constants, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +/* GIConstantInfo */ +_PyGI_DEFINE_INFO_TYPE("ConstantInfo", GIConstantInfo, PyGIBaseInfo_Type); + +static PyObject * +_wrap_g_constant_info_get_value (PyGIBaseInfo *self) +{ + GITypeInfo *type_info; + GArgument value; + PyObject *py_value; + + if (g_constant_info_get_value((GIConstantInfo *)self->info, &value) < 0) { + PyErr_SetString(PyExc_RuntimeError, "unable to get value"); + return NULL; + } + + type_info = g_constant_info_get_type((GIConstantInfo *)self->info); + + py_value = _pygi_argument_to_object(&value, type_info, GI_TRANSFER_NOTHING); + + g_base_info_unref((GIBaseInfo *)type_info); + + return py_value; +} + +static PyMethodDef _PyGIConstantInfo_methods[] = { + { "get_value", (PyCFunction)_wrap_g_constant_info_get_value, METH_NOARGS }, + { NULL, NULL, 0 } +}; + +/* GIValueInfo */ +_PyGI_DEFINE_INFO_TYPE("ValueInfo", GIValueInfo, PyGIBaseInfo_Type); + +static PyObject * +_wrap_g_value_info_get_value (PyGIBaseInfo *self) +{ + glong value; + + value = g_value_info_get_value((GIValueInfo *)self->info); + + return PyInt_FromLong(value); +} + + +static PyMethodDef _PyGIValueInfo_methods[] = { + { "get_value", (PyCFunction)_wrap_g_value_info_get_value, METH_NOARGS }, + { NULL, NULL, 0 } +}; + + +/* GIFieldInfo */ +_PyGI_DEFINE_INFO_TYPE("FieldInfo", GIFieldInfo, PyGIBaseInfo_Type); + +static PyObject * +_wrap_g_field_info_get_value (PyGIBaseInfo *self, + PyObject *args) +{ + PyObject *instance; + GIBaseInfo *container_info; + GIInfoType container_info_type; + gpointer pointer; + GITypeInfo *field_type_info; + GArgument value; + PyObject *py_value = NULL; + + if (!PyArg_ParseTuple(args, "O:FieldInfo.get_value", &instance)) { + return NULL; + } + + container_info = g_base_info_get_container(self->info); + g_assert(container_info != NULL); + + /* Check the instance. */ + if (!_pygi_g_registered_type_info_check_object((GIRegisteredTypeInfo *)container_info, TRUE, instance)) { + _PyGI_ERROR_PREFIX("argument 1: "); + return NULL; + } + + /* Get the pointer to the container. */ + container_info_type = g_base_info_get_type(container_info); + switch (container_info_type) { + case GI_INFO_TYPE_UNION: + PyErr_SetString(PyExc_NotImplementedError, "getting a field from an union is not supported yet"); + return NULL; + case GI_INFO_TYPE_STRUCT: + pointer = pyg_boxed_get(instance, void); + break; + case GI_INFO_TYPE_OBJECT: + pointer = pygobject_get(instance); + break; + default: + /* Other types don't have fields. */ + g_assert_not_reached(); + } + + /* Get the field's value. */ + field_type_info = g_field_info_get_type((GIFieldInfo *)self->info); + + /* A few types are not handled by g_field_info_get_field, so do it here. */ + if (!g_type_info_is_pointer(field_type_info) + && g_type_info_get_tag(field_type_info) == GI_TYPE_TAG_INTERFACE) { + GIBaseInfo *info; + GIInfoType info_type; + + if (!(g_field_info_get_flags((GIFieldInfo *)self->info) & GI_FIELD_IS_READABLE)) { + PyErr_SetString(PyExc_RuntimeError, "field is not readable"); + goto out; + } + + info = g_type_info_get_interface(field_type_info); + + info_type = g_base_info_get_type(info); + + g_base_info_unref(info); + + switch(info_type) { + case GI_INFO_TYPE_UNION: + PyErr_SetString(PyExc_NotImplementedError, "getting an union is not supported yet"); + goto out; + case GI_INFO_TYPE_STRUCT: + { + gsize offset; + + offset = g_field_info_get_offset((GIFieldInfo *)self->info); + + value.v_pointer = pointer + offset; + + goto argument_to_object; + } + default: + /* Fallback. */ + break; + } + } + + if (!g_field_info_get_field((GIFieldInfo *)self->info, pointer, &value)) { + PyErr_SetString(PyExc_RuntimeError, "unable to get the value"); + goto out; + } + +argument_to_object: + py_value = _pygi_argument_to_object(&value, field_type_info, GI_TRANSFER_NOTHING); + +out: + g_base_info_unref((GIBaseInfo *)field_type_info); + + return py_value; +} + +static PyObject * +_wrap_g_field_info_set_value (PyGIBaseInfo *self, + PyObject *args) +{ + PyObject *instance; + PyObject *py_value; + GIBaseInfo *container_info; + GIInfoType container_info_type; + gpointer pointer; + GITypeInfo *field_type_info; + GArgument value; + PyObject *retval = NULL; + + if (!PyArg_ParseTuple(args, "OO:FieldInfo.set_value", &instance, &py_value)) { + return NULL; + } + + container_info = g_base_info_get_container(self->info); + g_assert(container_info != NULL); + + /* Check the instance. */ + if (!_pygi_g_registered_type_info_check_object((GIRegisteredTypeInfo *)container_info, TRUE, instance)) { + _PyGI_ERROR_PREFIX("argument 1: "); + return NULL; + } + + /* Get the pointer to the container. */ + container_info_type = g_base_info_get_type(container_info); + switch (container_info_type) { + case GI_INFO_TYPE_UNION: + PyErr_SetString(PyExc_NotImplementedError, "setting a field in an union is not supported yet"); + return NULL; + case GI_INFO_TYPE_STRUCT: + pointer = pyg_boxed_get(instance, void); + break; + case GI_INFO_TYPE_OBJECT: + pointer = pygobject_get(instance); + break; + default: + /* Other types don't have fields. */ + g_assert_not_reached(); + } + + field_type_info = g_field_info_get_type((GIFieldInfo *)self->info); + + /* Check the value. */ + { + gboolean retval; + + retval = _pygi_g_type_info_check_object(field_type_info, TRUE, py_value); + if (retval < 0) { + goto out; + } + + if (!retval) { + _PyGI_ERROR_PREFIX("argument 2: "); + goto out; + } + } + + /* Set the field's value. */ + /* A few types are not handled by g_field_info_set_field, so do it here. */ + if (!g_type_info_is_pointer(field_type_info) + && g_type_info_get_tag(field_type_info) == GI_TYPE_TAG_INTERFACE) { + GIBaseInfo *info; + GIInfoType info_type; + + if (!(g_field_info_get_flags((GIFieldInfo *)self->info) & GI_FIELD_IS_WRITABLE)) { + PyErr_SetString(PyExc_RuntimeError, "field is not writable"); + goto out; + } + + info = g_type_info_get_interface(field_type_info); + + info_type = g_base_info_get_type(info); + + switch (info_type) { + case GI_INFO_TYPE_UNION: + PyErr_SetString(PyExc_NotImplementedError, "setting an union is not supported yet"); + goto out; + case GI_INFO_TYPE_STRUCT: + { + gboolean is_simple; + gsize offset; + gssize size; + + is_simple = pygi_g_struct_info_is_simple((GIStructInfo *)info); + + if (!is_simple) { + PyErr_SetString(PyExc_TypeError, + "cannot set a structure which has no well-defined ownership transfer rules"); + g_base_info_unref(info); + goto out; + } + + value = _pygi_argument_from_object(py_value, field_type_info, GI_TRANSFER_NOTHING); + if (PyErr_Occurred()) { + g_base_info_unref(info); + goto out; + } + + offset = g_field_info_get_offset((GIFieldInfo *)self->info); + size = g_struct_info_get_size((GIStructInfo *)info); + g_assert(size > 0); + + g_memmove(pointer + offset, value.v_pointer, size); + + g_base_info_unref(info); + + retval = Py_None; + goto out; + } + default: + /* Fallback. */ + break; + } + + g_base_info_unref(info); + } + + value = _pygi_argument_from_object(py_value, field_type_info, GI_TRANSFER_EVERYTHING); + if (PyErr_Occurred()) { + goto out; + } + + if (!g_field_info_set_field((GIFieldInfo *)self->info, pointer, &value)) { + _pygi_argument_release(&value, field_type_info, GI_TRANSFER_NOTHING, GI_DIRECTION_IN); + PyErr_SetString(PyExc_RuntimeError, "unable to set value for field"); + goto out; + } + + retval = Py_None; + +out: + g_base_info_unref((GIBaseInfo *)field_type_info); + + Py_XINCREF(retval); + return retval; +} + +static PyMethodDef _PyGIFieldInfo_methods[] = { + { "get_value", (PyCFunction)_wrap_g_field_info_get_value, METH_VARARGS }, + { "set_value", (PyCFunction)_wrap_g_field_info_set_value, METH_VARARGS }, + { NULL, NULL, 0 } +}; + + +/* GIUnresolvedInfo */ +_PyGI_DEFINE_INFO_TYPE("UnresolvedInfo", GIUnresolvedInfo, PyGIBaseInfo_Type); + +static PyMethodDef _PyGIUnresolvedInfo_methods[] = { + { NULL, NULL, 0 } +}; + +/* Private */ + +gchar * +_pygi_g_base_info_get_fullname (GIBaseInfo *info) +{ + GIBaseInfo *container_info; + gchar *fullname; + + container_info = g_base_info_get_container(info); + if (container_info != NULL) { + fullname = g_strdup_printf("%s.%s.%s", + g_base_info_get_namespace(container_info), + g_base_info_get_name(container_info), + g_base_info_get_name(info)); + } else { + fullname = g_strdup_printf("%s.%s", + g_base_info_get_namespace(info), + g_base_info_get_name(info)); + } + + if (fullname == NULL) { + PyErr_NoMemory(); + } + + return fullname; +} + +void +_pygi_info_register_types (PyObject *m) +{ +#define _PyGI_REGISTER_TYPE(m, type, name) \ + type.ob_type = &PyType_Type; \ + if (PyType_Ready(&type)) \ + return; \ + if (PyModule_AddObject(m, name, (PyObject *)&type)) \ + return + + _PyGI_REGISTER_TYPE(m, PyGIBaseInfo_Type, "BaseInfo"); + _PyGI_REGISTER_TYPE(m, PyGIUnresolvedInfo_Type, "UnresolvedInfo"); + _PyGI_REGISTER_TYPE(m, PyGICallableInfo_Type, "CallableInfo"); + _PyGI_REGISTER_TYPE(m, PyGIFunctionInfo_Type, "FunctionInfo"); + _PyGI_REGISTER_TYPE(m, PyGIRegisteredTypeInfo_Type, "RegisteredTypeInfo"); + _PyGI_REGISTER_TYPE(m, PyGIStructInfo_Type, "StructInfo"); + _PyGI_REGISTER_TYPE(m, PyGIEnumInfo_Type, "EnumInfo"); + _PyGI_REGISTER_TYPE(m, PyGIObjectInfo_Type, "ObjectInfo"); + _PyGI_REGISTER_TYPE(m, PyGIInterfaceInfo_Type, "InterfaceInfo"); + _PyGI_REGISTER_TYPE(m, PyGIConstantInfo_Type, "ConstantInfo"); + _PyGI_REGISTER_TYPE(m, PyGIValueInfo_Type, "ValueInfo"); + _PyGI_REGISTER_TYPE(m, PyGIFieldInfo_Type, "FieldInfo"); + +#undef _PyGI_REGISTER_TYPE +} diff --git a/gi/pygi-info.h b/gi/pygi-info.h new file mode 100644 index 00000000..437ef9a7 --- /dev/null +++ b/gi/pygi-info.h @@ -0,0 +1,64 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGI_INFO_H__ +#define __PYGI_INFO_H__ + +#include + +#include + +G_BEGIN_DECLS + +gboolean pygi_g_struct_info_is_simple (GIStructInfo *struct_info); + + +/* Private */ + +extern PyTypeObject PyGIBaseInfo_Type; +extern PyTypeObject PyGICallableInfo_Type; +extern PyTypeObject PyGIFunctionInfo_Type; +extern PyTypeObject PyGIRegisteredTypeInfo_Type; +extern PyTypeObject PyGIStructInfo_Type; +extern PyTypeObject PyGIEnumInfo_Type; +extern PyTypeObject PyGIObjectInfo_Type; +extern PyTypeObject PyGIInterfaceInfo_Type; +extern PyTypeObject PyGIConstantInfo_Type; +extern PyTypeObject PyGIValueInfo_Type; +extern PyTypeObject PyGIFieldInfo_Type; +extern PyTypeObject PyGIUnresolvedInfo_Type; + +#define PyGIBaseInfo_GET_GI_INFO(object) g_base_info_ref(((PyGIBaseInfo *)object)->info) + +PyObject* _pygi_info_new (GIBaseInfo *info); +GIBaseInfo* _pygi_object_get_gi_info (PyObject *object, + PyTypeObject *type); + +gchar* _pygi_g_base_info_get_fullname (GIBaseInfo *info); + +gsize _pygi_g_type_tag_size (GITypeTag type_tag); +gsize _pygi_g_type_info_size (GITypeInfo *type_info); + +void _pygi_info_register_types (PyObject *m); + +G_END_DECLS + +#endif /* __PYGI_INFO_H__ */ diff --git a/gi/pygi-private.h b/gi/pygi-private.h new file mode 100644 index 00000000..6ca85c86 --- /dev/null +++ b/gi/pygi-private.h @@ -0,0 +1,55 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + */ +#ifndef __PYGI_PRIVATE_H__ +#define __PYGI_PRIVATE_H__ + +#ifdef __PYGI_H__ +# error "Import pygi.h or pygi-private.h, but not both" +#endif + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "pygi.h" + +#include "pygobject-external.h" + +#include "pygi-repository.h" +#include "pygi-info.h" +#include "pygi-struct.h" +#include "pygi-argument.h" +#include "pygi-type.h" + +G_BEGIN_DECLS + +#define _PyGI_ERROR_PREFIX(format, ...) G_STMT_START { \ + PyObject *py_error_prefix; \ + py_error_prefix = PyString_FromFormat(format, ## __VA_ARGS__); \ + if (py_error_prefix != NULL) { \ + PyObject *py_error_type, *py_error_value, *py_error_traceback; \ + PyErr_Fetch(&py_error_type, &py_error_value, &py_error_traceback); \ + if (PyString_Check(py_error_value)) { \ + PyString_ConcatAndDel(&py_error_prefix, py_error_value); \ + if (py_error_prefix != NULL) { \ + py_error_value = py_error_prefix; \ + } \ + } \ + PyErr_Restore(py_error_type, py_error_value, py_error_traceback); \ + } \ +} G_STMT_END + + +/* Redefine g_array_index because we want it to return the i-th element, casted + * to the type t, of the array a, and not the i-th element of the array a + * casted to the type t. */ +#define _g_array_index(a,t,i) \ + *(t *)((a)->data + g_array_get_element_size(a) * (i)) + + +G_END_DECLS + +#endif /* __PYGI_PRIVATE_H__ */ diff --git a/gi/pygi-repository.c b/gi/pygi-repository.c new file mode 100644 index 00000000..f84fc7b1 --- /dev/null +++ b/gi/pygi-repository.c @@ -0,0 +1,238 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 Johan Dahlin + * + * pygi-repository.c: GIRepository wrapper. + * + * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "pygi-private.h" + +PyObject *PyGIRepositoryError; + +static PyMethodDef _PyGIRepository_methods[]; + +PyTypeObject PyGIRepository_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "gi.Repository", /* tp_name */ + sizeof(PyGIRepository), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)NULL, /* tp_dealloc */ + (printfunc)NULL, /* tp_print */ + (getattrfunc)NULL, /* tp_getattr */ + (setattrfunc)NULL, /* tp_setattr */ + (cmpfunc)NULL, /* tp_compare */ + (reprfunc)NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + (hashfunc)NULL, /* tp_hash */ + (ternaryfunc)NULL, /* tp_call */ + (reprfunc)NULL, /* tp_str */ + (getattrofunc)NULL, /* tp_getattro */ + (setattrofunc)NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT, /* tp_flags */ + NULL, /* tp_doc */ + (traverseproc)NULL, /* tp_traverse */ + (inquiry)NULL, /* tp_clear */ + (richcmpfunc)NULL, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)NULL, /* tp_iter */ + (iternextfunc)NULL, /* tp_iternext */ + _PyGIRepository_methods, /* tp_methods */ +}; + +static PyObject * +_wrap_g_irepository_get_default (PyObject *self) +{ + static PyGIRepository *repository = NULL; + + if (!repository) { + repository = (PyGIRepository *)PyObject_New(PyGIRepository, &PyGIRepository_Type); + if (repository == NULL) { + return NULL; + } + + repository->repository = g_irepository_get_default(); + } + + Py_INCREF((PyObject *)repository); + return (PyObject *)repository; +} + +static PyObject * +_wrap_g_irepository_require (PyGIRepository *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "namespace", "version", "lazy", NULL }; + + const char *namespace_; + const char *version = NULL; + PyObject *lazy = NULL; + GIRepositoryLoadFlags flags = 0; + GTypelib *typelib; + GError *error; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|sO:Repository.require", + kwlist, &namespace_, &version, &lazy)) { + return NULL; + } + + if (lazy != NULL && PyObject_IsTrue(lazy)) { + flags |= G_IREPOSITORY_LOAD_FLAG_LAZY; + } + + error = NULL; + typelib = g_irepository_require(self->repository, namespace_, version, flags, &error); + if (error != NULL) { + PyErr_SetString(PyGIRepositoryError, error->message); + g_error_free(error); + return NULL; + } + + Py_RETURN_NONE; +} + +static PyObject * +_wrap_g_irepository_find_by_name (PyGIRepository *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "namespace", "name", NULL }; + + const char *namespace_; + const char *name; + GIBaseInfo *info; + PyObject *py_info; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "ss:Repository.find_by_name", kwlist, &namespace_, &name)) { + return NULL; + } + + info = g_irepository_find_by_name(self->repository, namespace_, name); + if (info == NULL) { + Py_RETURN_NONE; + } + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + return py_info; +} + +static PyObject * +_wrap_g_irepository_get_infos (PyGIRepository *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "namespace", NULL }; + + const char *namespace_; + gssize n_infos; + PyObject *infos; + gssize i; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s:Repository.get_infos", + kwlist, &namespace_)) { + return NULL; + } + + n_infos = g_irepository_get_n_infos(self->repository, namespace_); + if (n_infos < 0) { + PyErr_Format(PyExc_RuntimeError, "Namespace '%s' not loaded", namespace_); + return NULL; + } + + infos = PyTuple_New(n_infos); + + for (i = 0; i < n_infos; i++) { + GIBaseInfo *info; + PyObject *py_info; + + info = g_irepository_get_info(self->repository, namespace_, i); + g_assert(info != NULL); + + py_info = _pygi_info_new(info); + + g_base_info_unref(info); + + if (py_info == NULL) { + Py_CLEAR(infos); + break; + } + + PyTuple_SET_ITEM(infos, i, py_info); + } + + return infos; +} + +static PyObject * +_wrap_g_irepository_get_typelib_path (PyGIRepository *self, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { "namespace", NULL }; + const char *namespace_; + const gchar *typelib_path; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, + "s:Repository.get_typelib_path", kwlist, &namespace_)) { + return NULL; + } + + typelib_path = g_irepository_get_typelib_path(self->repository, namespace_); + if (typelib_path == NULL) { + PyErr_Format(PyExc_RuntimeError, "Namespace '%s' not loaded", namespace_); + return NULL; + } + + return PyString_FromString(typelib_path); +} + +static PyMethodDef _PyGIRepository_methods[] = { + { "get_default", (PyCFunction)_wrap_g_irepository_get_default, METH_STATIC|METH_NOARGS }, + { "require", (PyCFunction)_wrap_g_irepository_require, METH_VARARGS|METH_KEYWORDS }, + { "get_infos", (PyCFunction)_wrap_g_irepository_get_infos, METH_VARARGS|METH_KEYWORDS }, + { "find_by_name", (PyCFunction)_wrap_g_irepository_find_by_name, METH_VARARGS|METH_KEYWORDS }, + { "get_typelib_path", (PyCFunction)_wrap_g_irepository_get_typelib_path, METH_VARARGS|METH_KEYWORDS }, + { NULL, NULL, 0 } +}; + +void +_pygi_repository_register_types (PyObject *m) +{ + PyGIRepository_Type.ob_type = &PyType_Type; + if (PyType_Ready(&PyGIRepository_Type)) { + return; + } + if (PyModule_AddObject(m, "Repository", (PyObject *)&PyGIRepository_Type)) { + return; + } + + PyGIRepositoryError = PyErr_NewException("gi.RepositoryError", NULL, NULL); + if (PyModule_AddObject(m, "RepositoryError", PyGIRepositoryError)) { + return; + } +} + diff --git a/gi/pygi-repository.h b/gi/pygi-repository.h new file mode 100644 index 00000000..d8eb8cfd --- /dev/null +++ b/gi/pygi-repository.h @@ -0,0 +1,39 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGI_REPOSITORY_H__ +#define __PYGI_REPOSITORY_H__ + +#include + +G_BEGIN_DECLS + +/* Private */ + +extern PyTypeObject PyGIRepository_Type; + +extern PyObject *PyGIRepositoryError; + +void _pygi_repository_register_types (PyObject *m); + +G_END_DECLS + +#endif /* __PYGI_REPOSITORY_H__ */ diff --git a/gi/pygi-struct.c b/gi/pygi-struct.c new file mode 100644 index 00000000..8b672c73 --- /dev/null +++ b/gi/pygi-struct.c @@ -0,0 +1,175 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2009 Simon van der Linden + * + * pygi-struct.c: wrapper to handle non-registered structures. + * + * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "pygi-private.h" + +#include +#include + +static void +_struct_dealloc (PyGIStruct *self) +{ + PyObject_GC_UnTrack((PyObject *)self); + + PyObject_ClearWeakRefs((PyObject *)self); + + if (self->free_on_dealloc) { + g_free(((PyGPointer *)self)->pointer); + } + + ((PyGPointer *)self)->ob_type->tp_free((PyObject *)self); +} + +static PyObject * +_struct_new (PyTypeObject *type, + PyObject *args, + PyObject *kwargs) +{ + static char *kwlist[] = { NULL }; + + GIBaseInfo *info; + gboolean is_simple; + gsize size; + gpointer pointer; + PyObject *self = NULL; + + if (!PyArg_ParseTupleAndKeywords(args, kwargs, "", kwlist)) { + return NULL; + } + + info = _pygi_object_get_gi_info((PyObject *)type, &PyGIStructInfo_Type); + if (info == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) { + PyErr_Format(PyExc_TypeError, "missing introspection information"); + } + return NULL; + } + + is_simple = pygi_g_struct_info_is_simple((GIStructInfo *)info); + if (!is_simple) { + PyErr_Format(PyExc_TypeError, "cannot create '%s' instances", type->tp_name); + goto out; + } + + size = g_struct_info_get_size((GIStructInfo *)info); + pointer = g_try_malloc(size); + if (pointer == NULL) { + PyErr_NoMemory(); + goto out; + } + + self = _pygi_struct_new(type, pointer, TRUE); + if (self == NULL) { + g_free(pointer); + } + +out: + g_base_info_unref(info); + + return (PyObject *)self; +} + +static int +_struct_init (PyObject *self, + PyObject *args, + PyObject *kwargs) +{ + /* Don't call PyGPointer's init, which raises an exception. */ + return 0; +} + + +PyTypeObject PyGIStruct_Type = { + PyObject_HEAD_INIT(NULL) + 0, + "gi.Struct", /* tp_name */ + sizeof(PyGIStruct), /* tp_basicsize */ + 0, /* tp_itemsize */ + (destructor)_struct_dealloc, /* tp_dealloc */ + (printfunc)NULL, /* tp_print */ + (getattrfunc)NULL, /* tp_getattr */ + (setattrfunc)NULL, /* tp_setattr */ + (cmpfunc)NULL, /* tp_compare */ + (reprfunc)NULL, /* tp_repr */ + NULL, /* tp_as_number */ + NULL, /* tp_as_sequence */ + NULL, /* tp_as_mapping */ + (hashfunc)NULL, /* tp_hash */ + (ternaryfunc)NULL, /* tp_call */ + (reprfunc)NULL, /* tp_str */ + (getattrofunc)NULL, /* tp_getattro */ + (setattrofunc)NULL, /* tp_setattro */ + NULL, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */ + NULL, /* tp_doc */ + (traverseproc)NULL, /* tp_traverse */ + (inquiry)NULL, /* tp_clear */ + (richcmpfunc)NULL, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + (getiterfunc)NULL, /* tp_iter */ + (iternextfunc)NULL, /* tp_iternext */ + NULL, /* tp_methods */ + NULL, /* tp_members */ + NULL, /* tp_getset */ + (PyTypeObject *)NULL, /* tp_base */ +}; + +PyObject * +_pygi_struct_new (PyTypeObject *type, + gpointer pointer, + gboolean free_on_dealloc) +{ + PyGIStruct *self; + GType g_type; + + if (!PyType_IsSubtype(type, &PyGIStruct_Type)) { + PyErr_SetString(PyExc_TypeError, "must be a subtype of gi.Struct"); + return NULL; + } + + self = (PyGIStruct *)type->tp_alloc(type, 0); + if (self == NULL) { + return NULL; + } + + g_type = pyg_type_from_object((PyObject *)type); + + ((PyGPointer *)self)->gtype = g_type; + ((PyGPointer *)self)->pointer = pointer; + self->free_on_dealloc = free_on_dealloc; + + return (PyObject *)self; +} + +void +_pygi_struct_register_types (PyObject *m) +{ + PyGIStruct_Type.ob_type = &PyType_Type; + PyGIStruct_Type.tp_base = &PyGPointer_Type; + PyGIStruct_Type.tp_new = (newfunc)_struct_new; + PyGIStruct_Type.tp_init = (initproc)_struct_init; + if (PyType_Ready(&PyGIStruct_Type)) + return; + if (PyModule_AddObject(m, "Struct", (PyObject *)&PyGIStruct_Type)) + return; +} diff --git a/gi/pygi-struct.h b/gi/pygi-struct.h new file mode 100644 index 00000000..963d05a3 --- /dev/null +++ b/gi/pygi-struct.h @@ -0,0 +1,40 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2009 Simon van der Linden + * + * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGI_STRUCT_H__ +#define __PYGI_STRUCT_H__ + +#include + +G_BEGIN_DECLS + +extern PyTypeObject PyGIStruct_Type; + +PyObject * +_pygi_struct_new (PyTypeObject *type, + gpointer pointer, + gboolean free_on_dealloc); + +void _pygi_struct_register_types (PyObject *m); + +G_END_DECLS + +#endif /* __PYGI_STRUCT_H__ */ diff --git a/gi/pygi-type.c b/gi/pygi-type.c new file mode 100644 index 00000000..c95da864 --- /dev/null +++ b/gi/pygi-type.c @@ -0,0 +1,96 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2009 Simon van der Linden + * + * pygi-type.c: helpers to lookup Python wrappers from GType and GIBaseInfo. + * + * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#include "pygi-private.h" + + +PyObject * +_pygi_type_import_by_gi_info (GIBaseInfo *info) +{ + const gchar *namespace_; + const gchar *name; + gchar *module_name; + PyObject *py_module; + PyObject *py_object; + + namespace_ = g_base_info_get_namespace(info); + name = g_base_info_get_name(info); + + module_name = g_strconcat("gi.repository.", namespace_, NULL); + + py_module = PyImport_ImportModule(module_name); + + g_free(module_name); + + if (py_module == NULL) { + return NULL; + } + + py_object = PyObject_GetAttrString(py_module, name); + + Py_DECREF(py_module); + + return py_object; +} + +PyObject * +pygi_type_import_by_g_type (GType g_type) +{ + GIRepository *repository; + GIBaseInfo *info; + PyObject *type; + + repository = g_irepository_get_default(); + + info = g_irepository_find_by_gtype(repository, g_type); + if (info == NULL) { + return NULL; + } + + type = _pygi_type_import_by_gi_info(info); + g_base_info_unref(info); + + return type; +} + +PyObject * +_pygi_type_get_from_g_type(GType g_type) +{ + PyObject *py_g_type; + PyObject *py_type; + + py_g_type = pyg_type_wrapper_new(g_type); + if (py_g_type == NULL) { + return NULL; + } + + py_type = PyObject_GetAttrString(py_g_type, "pytype"); + if (py_type == Py_None) { + py_type = pygi_type_import_by_g_type(g_type); + } + + Py_DECREF(py_g_type); + + return py_type; +} + diff --git a/gi/pygi-type.h b/gi/pygi-type.h new file mode 100644 index 00000000..19d07dca --- /dev/null +++ b/gi/pygi-type.h @@ -0,0 +1,43 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2009 Simon van der Linden + * + * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGI_TYPE_H__ +#define __PYGI_TYPE_H__ + +#include + +G_BEGIN_DECLS + +/* Public */ + +PyObject *pygi_type_import_by_g_type (GType g_type); + + +/* Private */ + +PyObject *_pygi_type_import_by_gi_info (GIBaseInfo *info); + +PyObject *_pygi_type_get_from_g_type (GType g_type); + + +G_END_DECLS + +#endif /* __PYGI_TYPE_H__ */ diff --git a/gi/pygi.h b/gi/pygi.h new file mode 100644 index 00000000..930017dc --- /dev/null +++ b/gi/pygi.h @@ -0,0 +1,99 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2005-2009 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGI_H__ +#define __PYGI_H__ + +#include + +#include + +G_BEGIN_DECLS + +typedef struct { + PyObject_HEAD + GIRepository *repository; +} PyGIRepository; + +typedef struct { + PyObject_HEAD + GIBaseInfo *info; + PyObject *inst_weakreflist; +} PyGIBaseInfo; + +typedef struct { + PyGPointer base; + gboolean free_on_dealloc; +} PyGIStruct; + + +struct PyGI_API { + PyObject* (*type_import_by_g_type) (GType g_type); +}; + + +#ifndef __PYGI_PRIVATE_H__ + +static struct PyGI_API *PyGI_API = NULL; + +#define pygi_type_import_by_g_type (PyGI_API->type_import_by_g_type) + + +static int +pygi_import (void) +{ + PyObject *module; + PyObject *api; + + if (PyGI_API != NULL) { + return 1; + } + + module = PyImport_ImportModule("gi"); + if (module == NULL) { + return -1; + } + + api = PyObject_GetAttrString(module, "_API"); + if (api == NULL) { + Py_DECREF(module); + return -1; + } + if (!PyCObject_Check(api)) { + Py_DECREF(module); + Py_DECREF(api); + PyErr_Format(PyExc_TypeError, "gi._API must be cobject, not %s", + api->ob_type->tp_name); + return -1; + } + + PyGI_API = (struct PyGI_API *)PyCObject_AsVoidPtr(api); + + Py_DECREF(api); + + return 0; +} + +#endif /* __PYGI_PRIVATE_H__ */ + +G_END_DECLS + +#endif /* __PYGI_H__ */ diff --git a/gi/pygobject-external.h b/gi/pygobject-external.h new file mode 100644 index 00000000..6dc63a5b --- /dev/null +++ b/gi/pygobject-external.h @@ -0,0 +1,83 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2009 Simon van der Linden + * + * 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.1 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 + * USA + */ + +#ifndef __PYGOBJECT_EXTERN_H__ +#define __PYGOBJECT_EXTERN_H__ + +#include + +G_BEGIN_DECLS + +static PyTypeObject *_PyGObject_Type; +static PyTypeObject *_PyGTypeWrapper_Type; + +#define PyGObject_Type (*_PyGObject_Type) +#define PyGTypeWrapper_Type (*_PyGTypeWrapper_Type) + + +static int +_pygobject_import (void) +{ + static gboolean imported = FALSE; + PyObject *from_list; + PyObject *module; + int retval = 0; + + if (imported) { + return 1; + } + + from_list = Py_BuildValue("(ss)", "GObject", "GTypeWrapper"); + if (from_list == NULL) { + return -1; + } + + module = PyImport_ImportModuleEx("gobject", NULL, NULL, from_list); + + Py_DECREF(from_list); + + if (module == NULL) { + return -1; + } + + _PyGObject_Type = (PyTypeObject *)PyObject_GetAttrString(module, "GObject"); + if (_PyGObject_Type == NULL) { + retval = -1; + goto out; + } + + _PyGTypeWrapper_Type = (PyTypeObject *)PyObject_GetAttrString(module, "GType"); + if (_PyGTypeWrapper_Type == NULL) { + retval = -1; + goto out; + } + + imported = TRUE; + +out: + Py_DECREF(module); + + return retval; +} + +G_END_DECLS + +#endif /* __PYGOBJECT_EXTERN_H__ */ diff --git a/gi/repository/Makefile.am b/gi/repository/Makefile.am new file mode 100644 index 00000000..c9138ce9 --- /dev/null +++ b/gi/repository/Makefile.am @@ -0,0 +1,8 @@ +PLATFORM_VERSION = 2.0 + +pkgpyexecdir = $(pyexecdir)/gtk-2.0/gi + +pygirepositorydir = $(pkgpyexecdir)/repository +pygirepository_PYTHON = \ + __init__.py + diff --git a/gi/repository/__init__.py b/gi/repository/__init__.py new file mode 100644 index 00000000..5c5552ac --- /dev/null +++ b/gi/repository/__init__.py @@ -0,0 +1,30 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab +# +# Copyright (C) 2009 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# USA + +from __future__ import absolute_import + +import sys + +from ..importer import DynamicImporter + +sys.meta_path.append(DynamicImporter('gi.repository')) + +del DynamicImporter +del sys diff --git a/gi/types.py b/gi/types.py new file mode 100644 index 00000000..10d7fdeb --- /dev/null +++ b/gi/types.py @@ -0,0 +1,163 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab +# +# Copyright (C) 2005-2009 Johan Dahlin +# +# types.py: base types for introspected items. +# +# 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.1 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 +# USA + +from __future__ import absolute_import + +import sys +import gobject + +from ._gi import \ + InterfaceInfo, \ + ObjectInfo, \ + StructInfo, \ + set_object_has_new_constructor + + +class Boxed(gobject.GBoxed): + # Instances of boxed structures cannot be constructed unless they have a + # specific constructor. + # + # To achieve this behavior, PyGBoxed_Type's constructor creates an + # instance, and the initializer eventually raises an exception. If things + # had been implemented correctly, PyGBoxed_Type.tp_new would have been set to + # NULL, and neither a creator nor an initializer wouldn't have been needed. + # + # In order to keep the code generic, we need to revert the right behavior. + + def __new__(cls): + raise TypeError, "instances of '%s' cannot be created" % cls.__name__ + + def __init__(self, *args, **kwargs): + pass + + +def Function(info): + + def function(*args): + return info.invoke(*args) + function.__info__ = info + function.__name__ = info.get_name() + function.__module__ = info.get_namespace() + + return function + + +def Constructor(info): + + def constructor(cls, *args): + cls_name = info.get_container().get_name() + if cls.__name__ != cls_name: + raise TypeError, '%s constructor cannot be used to create instances of a subclass' % cls_name + return info.invoke(cls, *args) + + constructor.__info__ = info + constructor.__name__ = info.get_name() + constructor.__module__ = info.get_namespace() + + return constructor + + +class MetaClassHelper(object): + + def _setup_methods(cls): + for method_info in cls.__info__.get_methods(): + name = method_info.get_name() + function = Function(method_info) + if method_info.is_method(): + method = function + elif method_info.is_constructor(): + continue + else: + method = staticmethod(function) + setattr(cls, name, method) + + def _setup_fields(cls): + for field_info in cls.__info__.get_fields(): + name = field_info.get_name().replace('-', '_') + setattr(cls, name, property(field_info.get_value, field_info.set_value)) + + def _setup_constants(cls): + for constant_info in cls.__info__.get_constants(): + name = constant_info.get_name() + value = constant_info.get_value() + setattr(cls, name, value) + + +class GObjectMeta(gobject.GObjectMeta, MetaClassHelper): + + def _setup_constructors(cls): + for method_info in cls.__info__.get_methods(): + if method_info.is_constructor(): + name = method_info.get_name() + constructor = classmethod(Constructor(method_info)) + setattr(cls, name, constructor) + + def __init__(cls, name, bases, dict_): + super(GObjectMeta, cls).__init__(name, bases, dict_) + + # Avoid touching anything else than the base class. + if cls.__name__ != cls.__info__.get_name(): + return; + + cls._setup_methods() + cls._setup_constants() + + if (isinstance(cls.__info__, ObjectInfo)): + cls._setup_fields() + cls._setup_constructors() + set_object_has_new_constructor(cls.__info__.get_g_type()) + + +class StructMeta(type, MetaClassHelper): + + def _setup_constructors(cls): + constructor_infos = [] + default_constructor_info = None + + for method_info in cls.__info__.get_methods(): + if method_info.is_constructor(): + name = method_info.get_name() + constructor = classmethod(Function(method_info)) + + setattr(cls, name, constructor) + + constructor_infos.append(method_info) + if name == "new": + default_constructor_info = method_info + + if default_constructor_info is None and constructor_infos: + default_constructor_info = constructor_infos[0] + + if default_constructor_info is not None: + cls.__new__ = staticmethod(Function(default_constructor_info)) + + def __init__(cls, name, bases, dict_): + super(StructMeta, cls).__init__(name, bases, dict_) + + # Avoid touching anything else than the base class. + if cls.__name__ != cls.__info__.get_name(): + return; + + cls._setup_fields() + cls._setup_methods() + cls._setup_constructors() + diff --git a/tests/Makefile.am b/tests/Makefile.am new file mode 100644 index 00000000..a014bfde --- /dev/null +++ b/tests/Makefile.am @@ -0,0 +1,48 @@ + +noinst_LTLIBRARIES = libtestgi.la + +libtestgi_la_CFLAGS = $(GNOME_CFLAGS) +libtestgi_la_LDFLAGS = -avoid-version +libtestgi_la_LIBADD = $(GNOME_LIBS) +libtestgi_la_SOURCES = \ + libtestgi.c \ + libtestgi.h + +# Force linking of a shared object. +libtestgi_la_LINK = $(LINK) -rpath $(pkgpyexecdir) + +TestGI-0.0.gir: libtestgi.la + $(AM_V_GEN) \ + $(INTROSPECTION_SCANNER) -v \ + --namespace TestGI \ + --nsversion 0.0 \ + $(GNOME_CFLAGS) \ + --include GObject-2.0 \ + --library libtestgi.la \ + --libtool "$(top_builddir)/libtool" \ + --pkg gobject-2.0 \ + --output $@ \ + $(addprefix $(srcdir)/,$(libtestgi_la_SOURCES)) + +BUILT_GIRSOURCES = TestGI-0.0.gir + +noinst_PYTHON = \ + runtests.py \ + test_gi.py + +nodist_noinst_DATA = $(BUILT_GIRSOURCES:.gir=.typelib) + +CLEANFILES = \ + $(BUILT_GIRSOURCES) \ + $(BUILT_GIRSOURCES:.gir=.typelib) + + +check-local: + GI_TYPELIB_PATH=$(srcdir)$${GI_TYPELIB_PATH:+:$$GI_TYPELIB_PATH} \ + LD_LIBRARY_PATH=$(srcdir)/.libs$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH} \ + $(PYTHON) $(srcdir)/runtests.py $$TEST_NAMES + +.gir.typelib: + $(AM_V_GEN) \ + LD_LIBRARY_PATH=$(srcdir)/.libs$${LD_LIBRARY_PATH:+:$$LD_LIBRARY_PATH} \ + $(INTROSPECTION_COMPILER) --includedir=$(srcdir) $< -o $(@F) diff --git a/tests/libtestgi.c b/tests/libtestgi.c new file mode 100644 index 00000000..ddc99b10 --- /dev/null +++ b/tests/libtestgi.c @@ -0,0 +1,3397 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + */ + +#include "libtestgi.h" + +#include + + +/* Booleans */ + +gboolean +test_gi_boolean_return_true (void) +{ + return TRUE; +} + +gboolean +test_gi_boolean_return_false (void) +{ + return FALSE; +} + +/** + * test_gi_boolean_return_ptr_true: + * Returns: (transfer none): + */ +gboolean * +test_gi_boolean_return_ptr_true (void) +{ + static gboolean bool_ = TRUE; + return &bool_; +} + +/** + * test_gi_boolean_return_ptr_false: + * Returns: (transfer none): + */ +gboolean * +test_gi_boolean_return_ptr_false (void) +{ + static gboolean bool_ = FALSE; + return &bool_; +} + +void +test_gi_boolean_in_true (gboolean bool_) +{ + g_assert (bool_ == TRUE); +} + +void +test_gi_boolean_in_false (gboolean bool_) +{ + g_assert (bool_ == FALSE); +} + +/** + * test_gi_boolean_in_ptr_true: + * bool_: (in): + */ +void +test_gi_boolean_in_ptr_true (gboolean *bool_) +{ + g_assert (*bool_ == TRUE); +} + +/** + * test_gi_boolean_in_ptr_false: + * bool_: (in): + */ +void +test_gi_boolean_in_ptr_false (gboolean *bool_) +{ + g_assert (*bool_ == FALSE); +} + +/** + * test_gi_boolean_out_true: + * bool_: (out): + */ +void +test_gi_boolean_out_true (gboolean *bool_) +{ + *bool_ = TRUE; +} + +/** + * test_gi_boolean_out_false: + * bool_: (out): + */ +void +test_gi_boolean_out_false (gboolean *bool_) +{ + *bool_ = FALSE; +} + +/** + * test_gi_boolean_inout_true_false: + * bool_: (inout): + */ +void +test_gi_boolean_inout_true_false (gboolean *bool_) +{ + g_assert (*bool_ == TRUE); + *bool_ = FALSE; +} + +/** + * test_gi_boolean_inout_false_true: + * bool_: (inout): + */ +void +test_gi_boolean_inout_false_true (gboolean *bool_) +{ + g_assert (*bool_ == FALSE); + *bool_ = TRUE; +} + + +/* Integers */ + +gint8 +test_gi_int8_return_max (void) +{ + return G_MAXINT8; +} + +gint8 +test_gi_int8_return_min (void) +{ + return G_MININT8; +} + +/** + * test_gi_int8_return_ptr_max: + * Returns: (transfer none): + */ +gint8 * +test_gi_int8_return_ptr_max (void) +{ + static gint8 int8 = G_MAXINT8; + return &int8; +} + +/** + * test_gi_int8_return_ptr_min: + * Returns: (transfer none): + */ +gint8 * +test_gi_int8_return_ptr_min (void) +{ + static gint8 int8 = G_MININT8; + return &int8; +} + +void +test_gi_int8_in_max (gint8 int8) +{ + g_assert(int8 == G_MAXINT8); +} + +void +test_gi_int8_in_min (gint8 int8) +{ + g_assert(int8 == G_MININT8); +} + +/** + * test_gi_int8_in_ptr_max: + * int8: (in): + */ +void +test_gi_int8_in_ptr_max (gint8 *int8) +{ + g_assert(*int8 == G_MAXINT8); +} + +/** + * test_gi_int8_in_ptr_min: + * int8: (in): + */ +void +test_gi_int8_in_ptr_min (gint8 *int8) +{ + g_assert(*int8 == G_MININT8); +} + +/** + * test_gi_int8_out_max: + * int8: (out): + */ +void +test_gi_int8_out_max (gint8 *int8) +{ + *int8 = G_MAXINT8; +} + +/** + * test_gi_int8_out_min: + * int8: (out): + */ +void +test_gi_int8_out_min (gint8 *int8) +{ + *int8 = G_MININT8; +} + +/** + * test_gi_int8_inout_max_min: + * int8: (inout): + */ +void +test_gi_int8_inout_max_min (gint8 *int8) +{ + g_assert(*int8 == G_MAXINT8); + *int8 = G_MININT8; +} + +/** + * test_gi_int8_inout_min_max: + * int8: (inout): + */ +void +test_gi_int8_inout_min_max (gint8 *int8) +{ + g_assert(*int8 == G_MININT8); + *int8 = G_MAXINT8; +} + + +guint8 +test_gi_uint8_return (void) +{ + return G_MAXUINT8; +} + +/** + * test_gi_uint8_return_ptr: + * Returns: (transfer none): + */ +guint8 * +test_gi_uint8_return_ptr (void) +{ + static guint8 uint8 = G_MAXUINT8; + return &uint8; +} + +void +test_gi_uint8_in (guint8 uint8) +{ + g_assert(uint8 == G_MAXUINT8); +} + +/** + * test_gi_uint8_in_ptr: + * uint8: (in): + */ +void +test_gi_uint8_in_ptr (guint8 *uint8) +{ + g_assert(*uint8 == G_MAXUINT8); +} + +/** + * test_gi_uint8_out: + * uint8: (out): + */ +void +test_gi_uint8_out (guint8 *uint8) +{ + *uint8 = G_MAXUINT8; +} + +/** + * test_gi_uint8_inout: + * uint8: (inout): + */ +void +test_gi_uint8_inout (guint8 *uint8) +{ + g_assert(*uint8 == G_MAXUINT8); + *uint8 = 0; +} + + +gint16 +test_gi_int16_return_max (void) +{ + return G_MAXINT16; +} + +gint16 +test_gi_int16_return_min (void) +{ + return G_MININT16; +} + +/** + * test_gi_int16_return_ptr_max: + * Returns: (transfer none): + */ +gint16 * +test_gi_int16_return_ptr_max (void) +{ + static gint16 int16 = G_MAXINT16; + return &int16; +} + +/** + * test_gi_int16_return_ptr_min: + * Returns: (transfer none): + */ +gint16 * +test_gi_int16_return_ptr_min (void) +{ + static gint16 int16 = G_MININT16; + return &int16; +} + +void +test_gi_int16_in_max (gint16 int16) +{ + g_assert(int16 == G_MAXINT16); +} + +void +test_gi_int16_in_min (gint16 int16) +{ + g_assert(int16 == G_MININT16); +} + +/** + * test_gi_int16_in_ptr_max: + * int16: (in): + */ +void +test_gi_int16_in_ptr_max (gint16 *int16) +{ + g_assert(*int16 == G_MAXINT16); +} + +/** + * test_gi_int16_in_ptr_min: + * int16: (in): + */ +void +test_gi_int16_in_ptr_min (gint16 *int16) +{ + g_assert(*int16 == G_MININT16); +} + +/** + * test_gi_int16_out_max: + * int16: (out): + */ +void +test_gi_int16_out_max (gint16 *int16) +{ + *int16 = G_MAXINT16; +} + +/** + * test_gi_int16_out_min: + * int16: (out): + */ +void +test_gi_int16_out_min (gint16 *int16) +{ + *int16 = G_MININT16; +} + +/** + * test_gi_int16_inout_max_min: + * int16: (inout): + */ +void +test_gi_int16_inout_max_min (gint16 *int16) +{ + g_assert(*int16 == G_MAXINT16); + *int16 = G_MININT16; +} + +/** + * test_gi_int16_inout_min_max: + * int16: (inout): + */ +void +test_gi_int16_inout_min_max (gint16 *int16) +{ + g_assert(*int16 == G_MININT16); + *int16 = G_MAXINT16; +} + + +guint16 +test_gi_uint16_return (void) +{ + return G_MAXUINT16; +} + +/** + * test_gi_uint16_return_ptr: + * Returns: (transfer none): + */ +guint16 * +test_gi_uint16_return_ptr (void) +{ + static guint16 uint16 = G_MAXUINT16; + return &uint16; +} + +void +test_gi_uint16_in (guint16 uint16) +{ + g_assert(uint16 == G_MAXUINT16); +} + +/** + * test_gi_uint16_in_ptr: + * uint16: (in): + */ +void +test_gi_uint16_in_ptr (guint16 *uint16) +{ + g_assert(*uint16 == G_MAXUINT16); +} + +/** + * test_gi_uint16_out: + * uint16: (out): + */ +void +test_gi_uint16_out (guint16 *uint16) +{ + *uint16 = G_MAXUINT16; +} + +/** + * test_gi_uint16_inout: + * uint16: (inout): + */ +void +test_gi_uint16_inout (guint16 *uint16) +{ + g_assert(*uint16 == G_MAXUINT16); + *uint16 = 0; +} + + +gint32 +test_gi_int32_return_max (void) +{ + return G_MAXINT32; +} + +gint32 +test_gi_int32_return_min (void) +{ + return G_MININT32; +} + +/** + * test_gi_int32_return_ptr_max: + * Returns: (transfer none): + */ +gint32 * +test_gi_int32_return_ptr_max (void) +{ + static gint32 int32 = G_MAXINT32; + return &int32; +} + +/** + * test_gi_int32_return_ptr_min: + * Returns: (transfer none): + */ +gint32 * +test_gi_int32_return_ptr_min (void) +{ + static gint32 int32 = G_MININT32; + return &int32; +} + +void +test_gi_int32_in_max (gint32 int32) +{ + g_assert(int32 == G_MAXINT32); +} + +void +test_gi_int32_in_min (gint32 int32) +{ + g_assert(int32 == G_MININT32); +} + +/** + * test_gi_int32_in_ptr_max: + * int32: (in): + */ +void +test_gi_int32_in_ptr_max (gint32 *int32) +{ + g_assert(*int32 == G_MAXINT32); +} + +/** + * test_gi_int32_in_ptr_min: + * int32: (in): + */ +void +test_gi_int32_in_ptr_min (gint32 *int32) +{ + g_assert(*int32 == G_MININT32); +} + +/** + * test_gi_int32_out_max: + * int32: (out): + */ +void +test_gi_int32_out_max (gint32 *int32) +{ + *int32 = G_MAXINT32; +} + +/** + * test_gi_int32_out_min: + * int32: (out): + */ +void +test_gi_int32_out_min (gint32 *int32) +{ + *int32 = G_MININT32; +} + +/** + * test_gi_int32_inout_max_min: + * int32: (inout): + */ +void +test_gi_int32_inout_max_min (gint32 *int32) +{ + g_assert(*int32 == G_MAXINT32); + *int32 = G_MININT32; +} + +/** + * test_gi_int32_inout_min_max: + * int32: (inout): + */ +void +test_gi_int32_inout_min_max (gint32 *int32) +{ + g_assert(*int32 == G_MININT32); + *int32 = G_MAXINT32; +} + + +guint32 +test_gi_uint32_return (void) +{ + return G_MAXUINT32; +} + +/** + * test_gi_uint32_return_ptr: + * Returns: (transfer none): + */ +guint32 * +test_gi_uint32_return_ptr (void) +{ + static guint32 uint32 = G_MAXUINT32; + return &uint32; +} + +void +test_gi_uint32_in (guint32 uint32) +{ + g_assert(uint32 == G_MAXUINT32); +} + +/** + * test_gi_uint32_in_ptr: + * uint32: (in): + */ +void +test_gi_uint32_in_ptr (guint32 *uint32) +{ + g_assert(*uint32 == G_MAXUINT32); +} + +/** + * test_gi_uint32_out: + * uint32: (out): + */ +void +test_gi_uint32_out (guint32 *uint32) +{ + *uint32 = G_MAXUINT32; +} + +/** + * test_gi_uint32_inout: + * uint32: (inout): + */ +void +test_gi_uint32_inout (guint32 *uint32) +{ + g_assert(*uint32 == G_MAXUINT32); + *uint32 = 0; +} + + +gint64 +test_gi_int64_return_max (void) +{ + return G_MAXINT64; +} + +gint64 +test_gi_int64_return_min (void) +{ + return G_MININT64; +} + +/** + * test_gi_int64_return_ptr_max: + * Returns: (transfer none): + */ +gint64 * +test_gi_int64_return_ptr_max (void) +{ + static gint64 int64 = G_MAXINT64; + return &int64; +} + +/** + * test_gi_int64_return_ptr_min: + * Returns: (transfer none): + */ +gint64 * +test_gi_int64_return_ptr_min (void) +{ + static gint64 int64 = G_MININT64; + return &int64; +} + +void +test_gi_int64_in_max (gint64 int64) +{ + g_assert(int64 == G_MAXINT64); +} + +void +test_gi_int64_in_min (gint64 int64) +{ + g_assert(int64 == G_MININT64); +} + +/** + * test_gi_int64_in_ptr_max: + * int64: (in): + */ +void +test_gi_int64_in_ptr_max (gint64 *int64) +{ + g_assert(*int64 == G_MAXINT64); +} + +/** + * test_gi_int64_in_ptr_min: + * int64: (in): + */ +void +test_gi_int64_in_ptr_min (gint64 *int64) +{ + g_assert(*int64 == G_MININT64); +} + +/** + * test_gi_int64_out_max: + * int64: (out): + */ +void +test_gi_int64_out_max (gint64 *int64) +{ + *int64 = G_MAXINT64; +} + +/** + * test_gi_int64_out_min: + * int64: (out): + */ +void +test_gi_int64_out_min (gint64 *int64) +{ + *int64 = G_MININT64; +} + +/** + * test_gi_int64_inout_max_min: + * int64: (inout): + */ +void +test_gi_int64_inout_max_min (gint64 *int64) +{ + g_assert(*int64 == G_MAXINT64); + *int64 = G_MININT64; +} + +/** + * test_gi_int64_inout_min_max: + * int64: (inout): + */ +void +test_gi_int64_inout_min_max (gint64 *int64) +{ + g_assert(*int64 == G_MININT64); + *int64 = G_MAXINT64; +} + + +guint64 +test_gi_uint64_return (void) +{ + return G_MAXUINT64; +} + +/** + * test_gi_uint64_return_ptr: + * Returns: (transfer none): + */ +guint64 * +test_gi_uint64_return_ptr (void) +{ + static guint64 uint64 = G_MAXUINT64; + return &uint64; +} + +void +test_gi_uint64_in (guint64 uint64) +{ + g_assert(uint64 == G_MAXUINT64); +} + +/** + * test_gi_uint64_in_ptr: + * uint64: (in): + */ +void +test_gi_uint64_in_ptr (guint64 *uint64) +{ + g_assert(*uint64 == G_MAXUINT64); +} + +/** + * test_gi_uint64_out: + * uint64: (out): + */ +void +test_gi_uint64_out (guint64 *uint64) +{ + *uint64 = G_MAXUINT64; +} + +/** + * test_gi_uint64_inout: + * uint64: (inout): + */ +void +test_gi_uint64_inout (guint64 *uint64) +{ + g_assert(*uint64 == G_MAXUINT64); + *uint64 = 0; +} + + +gshort +test_gi_short_return_max (void) +{ + return G_MAXSHORT; +} + +gshort +test_gi_short_return_min (void) +{ + return G_MINSHORT; +} + +/** + * test_gi_short_return_ptr_max: + * Returns: (transfer none): + */ +gshort * +test_gi_short_return_ptr_max (void) +{ + static gshort short_ = G_MAXSHORT; + return &short_; +} + +/** + * test_gi_short_return_ptr_min: + * Returns: (transfer none): + */ +gshort * +test_gi_short_return_ptr_min (void) +{ + static gshort short_ = G_MINSHORT; + return &short_; +} + +void +test_gi_short_in_max (gshort short_) +{ + g_assert(short_ == G_MAXSHORT); +} + +void +test_gi_short_in_min (gshort short_) +{ + g_assert(short_ == G_MINSHORT); +} + +/** + * test_gi_short_in_ptr_max: + * short_: (in): + */ +void +test_gi_short_in_ptr_max (gshort *short_) +{ + g_assert(*short_ == G_MAXSHORT); +} + +/** + * test_gi_short_in_ptr_min: + * short_: (in): + */ +void +test_gi_short_in_ptr_min (gshort *short_) +{ + g_assert(*short_ == G_MINSHORT); +} + +/** + * test_gi_short_out_max: + * short_: (out): + */ +void +test_gi_short_out_max (gshort *short_) +{ + *short_ = G_MAXSHORT; +} + +/** + * test_gi_short_out_min: + * short_: (out): + */ +void +test_gi_short_out_min (gshort *short_) +{ + *short_ = G_MINSHORT; +} + +/** + * test_gi_short_inout_max_min: + * short_: (inout): + */ +void +test_gi_short_inout_max_min (gshort *short_) +{ + g_assert(*short_ == G_MAXSHORT); + *short_ = G_MINSHORT; +} + +/** + * test_gi_short_inout_min_max: + * short_: (inout): + */ +void +test_gi_short_inout_min_max (gshort *short_) +{ + g_assert(*short_ == G_MINSHORT); + *short_ = G_MAXSHORT; +} + + +gushort +test_gi_ushort_return (void) +{ + return G_MAXUSHORT; +} + +/** + * test_gi_ushort_return_ptr: + * Returns: (transfer none): + */ +gushort * +test_gi_ushort_return_ptr (void) +{ + static gushort ushort = G_MAXUSHORT; + return &ushort; +} + +void +test_gi_ushort_in (gushort ushort) +{ + g_assert(ushort == G_MAXUSHORT); +} + +/** + * test_gi_ushort_in_ptr: + * ushort: (in): + */ +void +test_gi_ushort_in_ptr (gushort *ushort) +{ + g_assert(*ushort == G_MAXUSHORT); +} + +/** + * test_gi_ushort_out: + * ushort: (out): + */ +void +test_gi_ushort_out (gushort *ushort) +{ + *ushort = G_MAXUSHORT; +} + +/** + * test_gi_ushort_inout: + * ushort: (inout): + */ +void +test_gi_ushort_inout (gushort *ushort) +{ + g_assert(*ushort == G_MAXUSHORT); + *ushort = 0; +} + + +gint +test_gi_int_return_max (void) +{ + return G_MAXINT; +} + +gint +test_gi_int_return_min (void) +{ + return G_MININT; +} + +/** + * test_gi_int_return_ptr_max: + * Returns: (transfer none): + */ +gint * +test_gi_int_return_ptr_max (void) +{ + static gint int_ = G_MAXINT; + return &int_; +} + +/** + * test_gi_int_return_ptr_min: + * Returns: (transfer none): + */ +gint * +test_gi_int_return_ptr_min (void) +{ + static gint int_ = G_MININT; + return &int_; +} + +void +test_gi_int_in_max (gint int_) +{ + g_assert(int_ == G_MAXINT); +} + +void +test_gi_int_in_min (gint int_) +{ + g_assert(int_ == G_MININT); +} + +/** + * test_gi_int_in_ptr_max: + * int_: (in): + */ +void +test_gi_int_in_ptr_max (gint *int_) +{ + g_assert(*int_ == G_MAXINT); +} + +/** + * test_gi_int_in_ptr_min: + * int_: (in): + */ +void +test_gi_int_in_ptr_min (gint *int_) +{ + g_assert(*int_ == G_MININT); +} + +/** + * test_gi_int_out_max: + * int_: (out): + */ +void +test_gi_int_out_max (gint *int_) +{ + *int_ = G_MAXINT; +} + +/** + * test_gi_int_out_min: + * int_: (out): + */ +void +test_gi_int_out_min (gint *int_) +{ + *int_ = G_MININT; +} + +/** + * test_gi_int_inout_max_min: + * int_: (inout): + */ +void +test_gi_int_inout_max_min (gint *int_) +{ + g_assert(*int_ == G_MAXINT); + *int_ = G_MININT; +} + +/** + * test_gi_int_inout_min_max: + * int_: (inout): + */ +void +test_gi_int_inout_min_max (gint *int_) +{ + g_assert(*int_ == G_MININT); + *int_ = G_MAXINT; +} + + +guint +test_gi_uint_return (void) +{ + return G_MAXUINT; +} + +/** + * test_gi_uint_return_ptr: + * Returns: (transfer none): + */ +guint * +test_gi_uint_return_ptr (void) +{ + static guint uint = G_MAXUINT; + return &uint; +} + +void +test_gi_uint_in (guint uint) +{ + g_assert(uint == G_MAXUINT); +} + +/** + * test_gi_uint_in_ptr: + * uint: (in): + */ +void +test_gi_uint_in_ptr (guint *uint) +{ + g_assert(*uint == G_MAXUINT); +} + +/** + * test_gi_uint_out: + * uint: (out): + */ +void +test_gi_uint_out (guint *uint) +{ + *uint = G_MAXUINT; +} + +/** + * test_gi_uint_inout: + * uint: (inout): + */ +void +test_gi_uint_inout (guint *uint) +{ + g_assert(*uint == G_MAXUINT); + *uint = 0; +} + + +glong +test_gi_long_return_max (void) +{ + return G_MAXLONG; +} + +glong +test_gi_long_return_min (void) +{ + return G_MINLONG; +} + +/** + * test_gi_long_return_ptr_max: + * Returns: (transfer none): + */ +glong * +test_gi_long_return_ptr_max (void) +{ + static glong long_ = G_MAXLONG; + return &long_; +} + +/** + * test_gi_long_return_ptr_min: + * Returns: (transfer none): + */ +glong * +test_gi_long_return_ptr_min (void) +{ + static glong long_ = G_MINLONG; + return &long_; +} + +void +test_gi_long_in_max (glong long_) +{ + g_assert(long_ == G_MAXLONG); +} + +void +test_gi_long_in_min (glong long_) +{ + g_assert(long_ == G_MINLONG); +} + +/** + * test_gi_long_in_ptr_max: + * long_: (in): + */ +void +test_gi_long_in_ptr_max (glong *long_) +{ + g_assert(*long_ == G_MAXLONG); +} + +/** + * test_gi_long_in_ptr_min: + * long_: (in): + */ +void +test_gi_long_in_ptr_min (glong *long_) +{ + g_assert(*long_ == G_MINLONG); +} + +/** + * test_gi_long_out_max: + * long_: (out): + */ +void +test_gi_long_out_max (glong *long_) +{ + *long_ = G_MAXLONG; +} + +/** + * test_gi_long_out_min: + * long_: (out): + */ +void +test_gi_long_out_min (glong *long_) +{ + *long_ = G_MINLONG; +} + +/** + * test_gi_long_inout_max_min: + * long_: (inout): + */ +void +test_gi_long_inout_max_min (glong *long_) +{ + g_assert(*long_ == G_MAXLONG); + *long_ = G_MINLONG; +} + +/** + * test_gi_long_inout_min_max: + * long_: (inout): + */ +void +test_gi_long_inout_min_max (glong *long_) +{ + g_assert(*long_ == G_MINLONG); + *long_ = G_MAXLONG; +} + + +gulong +test_gi_ulong_return (void) +{ + return G_MAXULONG; +} + +/** + * test_gi_ulong_return_ptr: + * Returns: (transfer none): + */ +gulong * +test_gi_ulong_return_ptr (void) +{ + static gulong ulong = G_MAXULONG; + return &ulong; +} + +void +test_gi_ulong_in (gulong ulong) +{ + g_assert(ulong == G_MAXULONG); +} + +/** + * test_gi_ulong_in_ptr: + * ulong: (in): + */ +void +test_gi_ulong_in_ptr (gulong *ulong) +{ + g_assert(*ulong == G_MAXULONG); +} + +/** + * test_gi_ulong_out: + * ulong: (out): + */ +void +test_gi_ulong_out (gulong *ulong) +{ + *ulong = G_MAXULONG; +} + +/** + * test_gi_ulong_inout: + * ulong: (inout): + */ +void +test_gi_ulong_inout (gulong *ulong) +{ + g_assert(*ulong == G_MAXULONG); + *ulong = 0; +} + + +gssize +test_gi_ssize_return_max (void) +{ + return G_MAXSSIZE; +} + +gssize +test_gi_ssize_return_min (void) +{ + return G_MINSSIZE; +} + +/** + * test_gi_ssize_return_ptr_max: + * Returns: (transfer none): + */ +gssize * +test_gi_ssize_return_ptr_max (void) +{ + static gssize ssize = G_MAXSSIZE; + return &ssize; +} + +/** + * test_gi_ssize_return_ptr_min: + * Returns: (transfer none): + */ +gssize * +test_gi_ssize_return_ptr_min (void) +{ + static gssize ssize = G_MINSSIZE; + return &ssize; +} + +void +test_gi_ssize_in_max (gssize ssize) +{ + g_assert(ssize == G_MAXSSIZE); +} + +void +test_gi_ssize_in_min (gssize ssize) +{ + g_assert(ssize == G_MINSSIZE); +} + +/** + * test_gi_ssize_in_ptr_max: + * ssize: (in): + */ +void +test_gi_ssize_in_ptr_max (gssize *ssize) +{ + g_assert(*ssize == G_MAXSSIZE); +} + +/** + * test_gi_ssize_in_ptr_min: + * ssize: (in): + */ +void +test_gi_ssize_in_ptr_min (gssize *ssize) +{ + g_assert(*ssize == G_MINSSIZE); +} + +/** + * test_gi_ssize_out_max: + * ssize: (out): + */ +void +test_gi_ssize_out_max (gssize *ssize) +{ + *ssize = G_MAXSSIZE; +} + +/** + * test_gi_ssize_out_min: + * ssize: (out): + */ +void +test_gi_ssize_out_min (gssize *ssize) +{ + *ssize = G_MINSSIZE; +} + +/** + * test_gi_ssize_inout_max_min: + * ssize: (inout): + */ +void +test_gi_ssize_inout_max_min (gssize *ssize) +{ + g_assert(*ssize == G_MAXSSIZE); + *ssize = G_MINSSIZE; +} + +/** + * test_gi_ssize_inout_min_max: + * ssize: (inout): + */ +void +test_gi_ssize_inout_min_max (gssize *ssize) +{ + g_assert(*ssize == G_MINSSIZE); + *ssize = G_MAXSSIZE; +} + + +gsize +test_gi_size_return (void) +{ + return G_MAXSIZE; +} + +/** + * test_gi_size_return_ptr: + * Returns: (transfer none): + */ +gsize * +test_gi_size_return_ptr (void) +{ + static gsize size = G_MAXSIZE; + return &size; +} + +void +test_gi_size_in (gsize size) +{ + g_assert(size == G_MAXSIZE); +} + +/** + * test_gi_size_in_ptr: + * size: (in): + */ +void +test_gi_size_in_ptr (gsize *size) +{ + g_assert(*size == G_MAXSIZE); +} + +/** + * test_gi_size_out: + * size: (out): + */ +void +test_gi_size_out (gsize *size) +{ + *size = G_MAXSIZE; +} + +/** + * test_gi_size_inout: + * size: (inout): + */ +void +test_gi_size_inout (gsize *size) +{ + g_assert(*size == G_MAXSIZE); + *size = 0; +} + + +gfloat +test_gi_float_return (void) +{ + return G_MAXFLOAT; +} + +/** + * test_gi_float_return_ptr: + * Returns: (transfer none): + */ +gfloat * +test_gi_float_return_ptr (void) +{ + static gfloat float_ = G_MAXFLOAT; + return &float_; +} + +void +test_gi_float_in (gfloat float_) +{ + g_assert(float_ == G_MAXFLOAT); +} + +/** + * test_gi_float_in_ptr: + * float_: (in): + */ +void +test_gi_float_in_ptr (gfloat *float_) +{ + g_assert(*float_ == G_MAXFLOAT); +} + +/** + * test_gi_float_out: + * float_: (out): + */ +void +test_gi_float_out (gfloat *float_) +{ + *float_ = G_MAXFLOAT; +} + +/** + * test_gi_float_inout: + * float_: (inout): + */ +void +test_gi_float_inout (gfloat *float_) +{ + g_assert(*float_ == G_MAXFLOAT); + *float_ = G_MINFLOAT; +} + + +gdouble +test_gi_double_return (void) +{ + return G_MAXDOUBLE; +} + +/** + * test_gi_double_return_ptr: + * Returns: (transfer none): + */ +gdouble * +test_gi_double_return_ptr (void) +{ + static gdouble double_ = G_MAXDOUBLE; + return &double_; +} + +void +test_gi_double_in (gdouble double_) +{ + g_assert(double_ == G_MAXDOUBLE); +} + +/** + * test_gi_double_in_ptr: + * double_: (in): + */ +void +test_gi_double_in_ptr (gdouble *double_) +{ + g_assert(*double_ == G_MAXDOUBLE); +} + +/** + * test_gi_double_out: + * double_: (out): + */ +void +test_gi_double_out (gdouble *double_) +{ + *double_ = G_MAXDOUBLE; +} + +/** + * test_gi_double_inout: + * double_: (inout): + */ +void +test_gi_double_inout (gdouble *double_) +{ + g_assert(*double_ == G_MAXDOUBLE); + *double_ = G_MINDOUBLE; +} + + +time_t +test_gi_time_t_return (void) +{ + return 1234567890; +} + +/** + * test_gi_time_t_return_ptr: + * Returns: (transfer none): + */ +time_t * +test_gi_time_t_return_ptr (void) +{ + static time_t time_t_ = 1234567890; + return &time_t_; +} + +void +test_gi_time_t_in (time_t time_t_) +{ + g_assert(time_t_ == 1234567890); +} + +/** + * test_gi_time_t_in_ptr: + * time_t_: (in): + */ +void +test_gi_time_t_in_ptr (time_t *time_t_) +{ + g_assert(*time_t_ == 1234567890); +} + +/** + * test_gi_time_t_out: + * time_t_: (out): + */ +void +test_gi_time_t_out (time_t *time_t_) +{ + *time_t_ = 1234567890; +} + +/** + * test_gi_time_t_inout: + * time_t_: (inout): + */ +void +test_gi_time_t_inout (time_t *time_t_) +{ + g_assert(*time_t_ == 1234567890); + *time_t_ = 0; +} + + +GType +test_gi_gtype_return (void) +{ + return G_TYPE_NONE; +} + +/** + * test_gi_gtype_return_ptr: + * Returns: (transfer none): + */ +GType * +test_gi_gtype_return_ptr (void) +{ + static GType gtype = G_TYPE_NONE; + return >ype; +} + +void +test_gi_gtype_in (GType gtype) +{ + g_assert(gtype == G_TYPE_NONE); +} + +/** + * test_gi_gtype_in_ptr: + * gtype: (in): + */ +void +test_gi_gtype_in_ptr (GType *gtype) +{ + g_assert(*gtype == G_TYPE_NONE); +} + +/** + * test_gi_gtype_out: + * gtype: (out): + */ +void +test_gi_gtype_out (GType *gtype) +{ + *gtype = G_TYPE_NONE; +} + +/** + * test_gi_gtype_inout: + * gtype: (inout): + */ +void +test_gi_gtype_inout (GType *gtype) +{ + g_assert(*gtype == G_TYPE_NONE); + *gtype = G_TYPE_INT; +} + + +const gchar * +test_gi_utf8_none_return (void) +{ + return TESTGI_CONSTANT_UTF8; +} + +gchar * +test_gi_utf8_full_return (void) +{ + return g_strdup(TESTGI_CONSTANT_UTF8); +} + +void +test_gi_utf8_none_in (const gchar *utf8) +{ + g_assert(strcmp(TESTGI_CONSTANT_UTF8, utf8) == 0); +} + +void +test_gi_utf8_full_in (gchar *utf8) +{ + g_assert(strcmp(TESTGI_CONSTANT_UTF8, utf8) == 0); + g_free(utf8); +} + +/** + * test_gi_utf8_none_out: + * utf8: (out) (transfer none): + */ +void +test_gi_utf8_none_out (gchar **utf8) +{ + *utf8 = TESTGI_CONSTANT_UTF8; +} + +/** + * test_gi_utf8_full_out: + * utf8: (out) (transfer full): + */ +void +test_gi_utf8_full_out (gchar **utf8) +{ + *utf8 = g_strdup(TESTGI_CONSTANT_UTF8); +} + +/** + * test_gi_utf8_none_inout: + * utf8: (inout) (transfer none): + */ +void +test_gi_utf8_none_inout (gchar **utf8) +{ + g_assert(strcmp(TESTGI_CONSTANT_UTF8, *utf8) == 0); + *utf8 = ""; +} + +/** + * test_gi_utf8_full_inout: + * utf8: (inout) (transfer full): + */ +void +test_gi_utf8_full_inout (gchar **utf8) +{ + g_assert(strcmp(TESTGI_CONSTANT_UTF8, *utf8) == 0); + g_free(*utf8); + *utf8 = g_strdup(""); +} + + +/** + * test_gi_array_fixed_int_return: + * Returns: (array fixed-size=4): + */ +const gint * +test_gi_array_fixed_int_return (void) +{ + static gint ints[] = {-1, 0, 1, 2}; + return ints; +} + +/** + * test_gi_array_fixed_short_return: + * Returns: (array fixed-size=4): + */ +const gshort * +test_gi_array_fixed_short_return (void) +{ + static gshort shorts[] = {-1, 0, 1, 2}; + return shorts; +} + +/** + * test_gi_array_fixed_int_in: + * @ints: (array fixed-size=4): + */ +void +test_gi_array_fixed_int_in (const gint *ints) +{ + g_assert(ints[0] == -1); + g_assert(ints[1] == 0); + g_assert(ints[2] == 1); + g_assert(ints[3] == 2); +} + +/** + * test_gi_array_fixed_short_in: + * @shorts: (array fixed-size=4): + */ +void +test_gi_array_fixed_short_in (const gshort *shorts) +{ + g_assert(shorts[0] == -1); + g_assert(shorts[1] == 0); + g_assert(shorts[2] == 1); + g_assert(shorts[3] == 2); +} + +/** + * test_gi_array_fixed_out: + * @ints: (out) (array fixed-size=4) (transfer none): + */ +void +test_gi_array_fixed_out (gint **ints) +{ + static gint values[] = {-1, 0, 1, 2}; + *ints = values; +} + +/** + * test_gi_array_fixed_inout: + * @ints: (inout) (array fixed-size=4) (transfer none): + */ +void +test_gi_array_fixed_inout (gint **ints) +{ + static gint values[] = {2, 1, 0, -1}; + + g_assert((*ints)[0] == -1); + g_assert((*ints)[1] == 0); + g_assert((*ints)[2] == 1); + g_assert((*ints)[3] == 2); + + *ints = values; +} + + +/** + * test_gi_array_return: + * Returns: (array length=length): + */ +const gint * +test_gi_array_return (gint *length) +{ + static gint ints[] = {-1, 0, 1, 2}; + + *length = 4; + return ints; +} + +/** + * test_gi_array_in: + * @ints: (array length=length): + */ +void +test_gi_array_in (const gint *ints, gint length) +{ + g_assert(length == 4); + g_assert(ints[0] == -1); + g_assert(ints[1] == 0); + g_assert(ints[2] == 1); + g_assert(ints[3] == 2); +} + +/** + * test_gi_array_out: + * @ints: (out) (array length=length) (transfer none): + */ +void +test_gi_array_out (gint **ints, gint *length) +{ + static gint values[] = {-1, 0, 1, 2}; + + *length = 4; + *ints = values; +} + +/** + * test_gi_array_inout: + * @ints: (inout) (array length=length) (transfer none): + * @length: (inout): + */ +void +test_gi_array_inout (gint **ints, gint *length) +{ + static gint values[] = {-2, -1, 0, 1, 2}; + + g_assert(*length == 4); + g_assert((*ints)[0] == -1); + g_assert((*ints)[1] == 0); + g_assert((*ints)[2] == 1); + g_assert((*ints)[3] == 2); + + *length = 5; + *ints = values; +} + + +/** + * test_gi_array_zero_terminated_return: + * Returns: (array zero-terminated=1) (transfer none): + */ +gchar ** +test_gi_array_zero_terminated_return (void) +{ + static gchar *values[] = {"0", "1", "2", NULL}; + return values; +} + +/** + * test_gi_array_zero_terminated_in: + * @utf8s: (array zero-terminated=1) (transfer none): + */ +void +test_gi_array_zero_terminated_in (gchar **utf8s) +{ + g_assert(g_strv_length(utf8s)); + g_assert(strcmp(utf8s[0], "0") == 0); + g_assert(strcmp(utf8s[1], "1") == 0); + g_assert(strcmp(utf8s[2], "2") == 0); +} + +/** + * test_gi_array_zero_terminated_out: + * @utf8s: (out) (array zero-terminated=1) (transfer none): + */ +void +test_gi_array_zero_terminated_out (gchar ***utf8s) +{ + static gchar *values[] = {"0", "1", "2", NULL}; + *utf8s = values; +} + +/** + * test_gi_array_zero_terminated_inout: + * @utf8s: (inout) (array zero-terminated=1) (transfer none): + */ +void +test_gi_array_zero_terminated_inout (gchar ***utf8s) +{ + static gchar *values[] = {"-1", "0", "1", "2", NULL}; + + g_assert(g_strv_length(*utf8s)); + g_assert(strcmp((*utf8s)[0], "0") == 0); + g_assert(strcmp((*utf8s)[1], "1") == 0); + g_assert(strcmp((*utf8s)[2], "2") == 0); + + *utf8s = values; +} + + +/** + * test_gi_glist_int_none_return: + * Returns: (element-type gint) (transfer none): + */ +GList * +test_gi_glist_int_none_return (void) +{ + static GList *list = NULL; + + if (list == NULL) { + list = g_list_append(list, GINT_TO_POINTER(-1)); + list = g_list_append(list, GINT_TO_POINTER(0)); + list = g_list_append(list, GINT_TO_POINTER(1)); + list = g_list_append(list, GINT_TO_POINTER(2)); + } + + return list; +} + +/** + * test_gi_glist_utf8_none_return: + * Returns: (element-type utf8) (transfer none): + */ +GList * +test_gi_glist_utf8_none_return (void) +{ + static GList *list = NULL; + + if (list == NULL) { + list = g_list_append(list, "0"); + list = g_list_append(list, "1"); + list = g_list_append(list, "2"); + } + + return list; +} + +/** + * test_gi_glist_utf8_container_return: + * Returns: (element-type utf8) (transfer container): + */ +GList * +test_gi_glist_utf8_container_return (void) +{ + GList *list = NULL; + + list = g_list_append(list, "0"); + list = g_list_append(list, "1"); + list = g_list_append(list, "2"); + + return list; +} + +/** + * test_gi_glist_utf8_full_return: + * Returns: (element-type utf8) (transfer full): + */ +GList * +test_gi_glist_utf8_full_return (void) +{ + GList *list = NULL; + + list = g_list_append(list, g_strdup("0")); + list = g_list_append(list, g_strdup("1")); + list = g_list_append(list, g_strdup("2")); + + return list; +} + +/** + * test_gi_glist_int_none_in: + * @list: (element-type gint) (transfer none): + */ +void +test_gi_glist_int_none_in (GList *list) +{ + g_assert(g_list_length(list) == 4); + g_assert(GPOINTER_TO_INT(g_list_nth_data(list, 0)) == -1); + g_assert(GPOINTER_TO_INT(g_list_nth_data(list, 1)) == 0); + g_assert(GPOINTER_TO_INT(g_list_nth_data(list, 2)) == 1); + g_assert(GPOINTER_TO_INT(g_list_nth_data(list, 3)) == 2); +} + +/** + * test_gi_glist_utf8_none_in: + * @list: (element-type utf8) (transfer none): + */ +void +test_gi_glist_utf8_none_in (GList *list) +{ + g_assert(g_list_length(list) == 3); + g_assert(strcmp(g_list_nth_data(list, 0), "0") == 0); + g_assert(strcmp(g_list_nth_data(list, 1), "1") == 0); + g_assert(strcmp(g_list_nth_data(list, 2), "2") == 0); +} + +/** + * test_gi_glist_utf8_container_in: + * @list: (element-type utf8) (transfer container): + */ +void +test_gi_glist_utf8_container_in (GList *list) +{ + g_assert(g_list_length(list) == 3); + g_assert(strcmp(g_list_nth_data(list, 0), "0") == 0); + g_assert(strcmp(g_list_nth_data(list, 1), "1") == 0); + g_assert(strcmp(g_list_nth_data(list, 2), "2") == 0); + g_list_free(list); +} + +/** + * test_gi_glist_utf8_full_in: + * @list: (element-type utf8) (transfer full): + */ +void +test_gi_glist_utf8_full_in (GList *list) +{ + g_assert(g_list_length(list) == 3); + g_assert(strcmp(g_list_nth_data(list, 0), "0") == 0); + g_assert(strcmp(g_list_nth_data(list, 1), "1") == 0); + g_assert(strcmp(g_list_nth_data(list, 2), "2") == 0); + g_free(g_list_nth_data(list, 0)); + g_free(g_list_nth_data(list, 1)); + g_free(g_list_nth_data(list, 2)); + g_list_free(list); +} + +/** + * test_gi_glist_utf8_none_out: + * @list: (out) (element-type utf8) (transfer none): + */ +void +test_gi_glist_utf8_none_out (GList **list) +{ + static GList *values = NULL; + + if (values == NULL) { + values = g_list_append(values, "0"); + values = g_list_append(values, "1"); + values = g_list_append(values, "2"); + } + + *list = values; +} + +/** + * test_gi_glist_utf8_container_out: + * @list: (out) (element-type utf8) (transfer container): + */ +void +test_gi_glist_utf8_container_out (GList **list) +{ + *list = NULL; + + *list = g_list_append(*list, "0"); + *list = g_list_append(*list, "1"); + *list = g_list_append(*list, "2"); +} + +/** + * test_gi_glist_utf8_full_out: + * @list: (out) (element-type utf8) (transfer full): + */ +void +test_gi_glist_utf8_full_out (GList **list) +{ + *list = NULL; + + *list = g_list_append(*list, g_strdup("0")); + *list = g_list_append(*list, g_strdup("1")); + *list = g_list_append(*list, g_strdup("2")); +} + +/** + * test_gi_glist_utf8_none_inout: + * @list: (inout) (element-type utf8) (transfer none): + */ +void +test_gi_glist_utf8_none_inout (GList **list) +{ + static GList *values = NULL; + + g_assert(g_list_length(*list) == 3); + g_assert(strcmp(g_list_nth_data(*list, 0), "0") == 0); + g_assert(strcmp(g_list_nth_data(*list, 1), "1") == 0); + g_assert(strcmp(g_list_nth_data(*list, 2), "2") == 0); + + if (values == NULL) { + values = g_list_append(values, "-2"); + values = g_list_append(values, "-1"); + values = g_list_append(values, "0"); + values = g_list_append(values, "1"); + } + + *list = values; +} + +/** + * test_gi_glist_utf8_container_inout: + * @list: (inout) (element-type utf8) (transfer container): + */ +void +test_gi_glist_utf8_container_inout (GList **list) +{ + g_assert(g_list_length(*list) == 3); + g_assert(strcmp(g_list_nth_data(*list, 0), "0") == 0); + g_assert(strcmp(g_list_nth_data(*list, 1), "1") == 0); + g_assert(strcmp(g_list_nth_data(*list, 2), "2") == 0); + + *list = g_list_remove_link(*list, g_list_last(*list)); + + *list = g_list_prepend(*list, "-1"); + *list = g_list_prepend(*list, "-2"); +} + +/** + * test_gi_glist_utf8_full_inout: + * @list: (inout) (element-type utf8) (transfer full): + */ +void +test_gi_glist_utf8_full_inout (GList **list) +{ + gpointer *data; + + g_assert(g_list_length(*list) == 3); + g_assert(strcmp(g_list_nth_data(*list, 0), "0") == 0); + g_assert(strcmp(g_list_nth_data(*list, 1), "1") == 0); + g_assert(strcmp(g_list_nth_data(*list, 2), "2") == 0); + + data = g_list_last(*list)->data; + *list = g_list_remove(*list, data); + g_free(data); + + *list = g_list_prepend(*list, g_strdup("-1")); + *list = g_list_prepend(*list, g_strdup("-2")); +} + + +/** + * test_gi_gslist_int_none_return: + * Returns: (element-type gint) (transfer none): + */ +GSList * +test_gi_gslist_int_none_return (void) +{ + static GSList *list = NULL; + + if (list == NULL) { + list = g_slist_prepend(list, GINT_TO_POINTER(-1)); + list = g_slist_prepend(list, GINT_TO_POINTER(0)); + list = g_slist_prepend(list, GINT_TO_POINTER(1)); + list = g_slist_prepend(list, GINT_TO_POINTER(2)); + list = g_slist_reverse(list); + } + + return list; +} + +/** + * test_gi_gslist_utf8_none_return: + * Returns: (element-type utf8) (transfer none): + */ +GSList * +test_gi_gslist_utf8_none_return (void) +{ + static GSList *list = NULL; + + if (list == NULL) { + list = g_slist_prepend(list, "0"); + list = g_slist_prepend(list, "1"); + list = g_slist_prepend(list, "2"); + list = g_slist_reverse(list); + } + + return list; +} + +/** + * test_gi_gslist_utf8_container_return: + * Returns: (element-type utf8) (transfer container): + */ +GSList * +test_gi_gslist_utf8_container_return (void) +{ + GSList *list = NULL; + + list = g_slist_prepend(list, "0"); + list = g_slist_prepend(list, "1"); + list = g_slist_prepend(list, "2"); + list = g_slist_reverse(list); + + return list; +} + +/** + * test_gi_gslist_utf8_full_return: + * Returns: (element-type utf8) (transfer full): + */ +GSList * +test_gi_gslist_utf8_full_return (void) +{ + GSList *list = NULL; + + list = g_slist_prepend(list, g_strdup("0")); + list = g_slist_prepend(list, g_strdup("1")); + list = g_slist_prepend(list, g_strdup("2")); + list = g_slist_reverse(list); + + return list; +} + +/** + * test_gi_gslist_int_none_in: + * @list: (element-type gint) (transfer none): + */ +void +test_gi_gslist_int_none_in (GSList *list) +{ + g_assert(g_slist_length(list) == 4); + g_assert(GPOINTER_TO_INT(g_slist_nth_data(list, 0)) == -1); + g_assert(GPOINTER_TO_INT(g_slist_nth_data(list, 1)) == 0); + g_assert(GPOINTER_TO_INT(g_slist_nth_data(list, 2)) == 1); + g_assert(GPOINTER_TO_INT(g_slist_nth_data(list, 3)) == 2); +} + +/** + * test_gi_gslist_utf8_none_in: + * @list: (element-type utf8) (transfer none): + */ +void +test_gi_gslist_utf8_none_in (GSList *list) +{ + g_assert(g_slist_length(list) == 3); + g_assert(strcmp(g_slist_nth_data(list, 0), "0") == 0); + g_assert(strcmp(g_slist_nth_data(list, 1), "1") == 0); + g_assert(strcmp(g_slist_nth_data(list, 2), "2") == 0); +} + +/** + * test_gi_gslist_utf8_container_in: + * @list: (element-type utf8) (transfer container): + */ +void +test_gi_gslist_utf8_container_in (GSList *list) +{ + g_assert(g_slist_length(list) == 3); + g_assert(strcmp(g_slist_nth_data(list, 0), "0") == 0); + g_assert(strcmp(g_slist_nth_data(list, 1), "1") == 0); + g_assert(strcmp(g_slist_nth_data(list, 2), "2") == 0); + g_slist_free(list); +} + +/** + * test_gi_gslist_utf8_full_in: + * @list: (element-type utf8) (transfer full): + */ +void +test_gi_gslist_utf8_full_in (GSList *list) +{ + g_assert(g_slist_length(list) == 3); + g_assert(strcmp(g_slist_nth_data(list, 0), "0") == 0); + g_assert(strcmp(g_slist_nth_data(list, 1), "1") == 0); + g_assert(strcmp(g_slist_nth_data(list, 2), "2") == 0); + g_free(g_slist_nth_data(list, 0)); + g_free(g_slist_nth_data(list, 1)); + g_free(g_slist_nth_data(list, 2)); + g_slist_free(list); +} + +/** + * test_gi_gslist_utf8_none_out: + * @list: (out) (element-type utf8) (transfer none): + */ +void +test_gi_gslist_utf8_none_out (GSList **list) +{ + static GSList *values = NULL; + + if (values == NULL) { + values = g_slist_prepend(values, "0"); + values = g_slist_prepend(values, "1"); + values = g_slist_prepend(values, "2"); + values = g_slist_reverse(values); + } + + *list = values; +} + +/** + * test_gi_gslist_utf8_container_out: + * @list: (out) (element-type utf8) (transfer container): + */ +void +test_gi_gslist_utf8_container_out (GSList **list) +{ + *list = NULL; + + *list = g_slist_prepend(*list, "0"); + *list = g_slist_prepend(*list, "1"); + *list = g_slist_prepend(*list, "2"); + *list = g_slist_reverse(*list); +} + +/** + * test_gi_gslist_utf8_full_out: + * @list: (out) (element-type utf8) (transfer full): + */ +void +test_gi_gslist_utf8_full_out (GSList **list) +{ + *list = NULL; + + *list = g_slist_prepend(*list, g_strdup("0")); + *list = g_slist_prepend(*list, g_strdup("1")); + *list = g_slist_prepend(*list, g_strdup("2")); + *list = g_slist_reverse(*list); +} + +/** + * test_gi_gslist_utf8_none_inout: + * @list: (inout) (element-type utf8) (transfer none): + */ +void +test_gi_gslist_utf8_none_inout (GSList **list) +{ + static GSList *values = NULL; + + g_assert(g_slist_length(*list) == 3); + g_assert(strcmp(g_slist_nth_data(*list, 0), "0") == 0); + g_assert(strcmp(g_slist_nth_data(*list, 1), "1") == 0); + g_assert(strcmp(g_slist_nth_data(*list, 2), "2") == 0); + + if (values == NULL) { + values = g_slist_prepend(values, "-2"); + values = g_slist_prepend(values, "-1"); + values = g_slist_prepend(values, "0"); + values = g_slist_prepend(values, "1"); + values = g_slist_reverse(values); + } + + *list = values; +} + +/** + * test_gi_gslist_utf8_container_inout: + * @list: (inout) (element-type utf8) (transfer container): + */ +void +test_gi_gslist_utf8_container_inout (GSList **list) +{ + g_assert(g_slist_length(*list) == 3); + g_assert(strcmp(g_slist_nth_data(*list, 0), "0") == 0); + g_assert(strcmp(g_slist_nth_data(*list, 1), "1") == 0); + g_assert(strcmp(g_slist_nth_data(*list, 2), "2") == 0); + + *list = g_slist_remove_link(*list, g_slist_last(*list)); + + *list = g_slist_prepend(*list, "-1"); + *list = g_slist_prepend(*list, "-2"); +} + +/** + * test_gi_gslist_utf8_full_inout: + * @list: (inout) (element-type utf8) (transfer full): + */ +void +test_gi_gslist_utf8_full_inout (GSList **list) +{ + gpointer *data; + + g_assert(g_slist_length(*list) == 3); + g_assert(strcmp(g_slist_nth_data(*list, 0), "0") == 0); + g_assert(strcmp(g_slist_nth_data(*list, 1), "1") == 0); + g_assert(strcmp(g_slist_nth_data(*list, 2), "2") == 0); + + data = g_slist_last(*list)->data; + *list = g_slist_remove(*list, data); + g_free(data); + + *list = g_slist_prepend(*list, g_strdup("-1")); + *list = g_slist_prepend(*list, g_strdup("-2")); +} + + +/** + * test_gi_ghashtable_int_none_return: + * Returns: (element-type gint gint) (transfer none): + */ +GHashTable * +test_gi_ghashtable_int_none_return (void) +{ + static GHashTable *hash_table = NULL; + + if (hash_table == NULL) { + hash_table = g_hash_table_new(NULL, NULL); + g_hash_table_insert(hash_table, GINT_TO_POINTER(-1), GINT_TO_POINTER(1)); + g_hash_table_insert(hash_table, GINT_TO_POINTER(0), GINT_TO_POINTER(0)); + g_hash_table_insert(hash_table, GINT_TO_POINTER(1), GINT_TO_POINTER(-1)); + g_hash_table_insert(hash_table, GINT_TO_POINTER(2), GINT_TO_POINTER(-2)); + } + + return hash_table; +} + +/** + * test_gi_ghashtable_utf8_none_return: + * Returns: (element-type utf8 utf8) (transfer none): + */ +GHashTable * +test_gi_ghashtable_utf8_none_return (void) +{ + static GHashTable *hash_table = NULL; + + if (hash_table == NULL) { + hash_table = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(hash_table, "-1", "1"); + g_hash_table_insert(hash_table, "0", "0"); + g_hash_table_insert(hash_table, "1", "-1"); + g_hash_table_insert(hash_table, "2", "-2"); + } + + return hash_table; +} + +/** + * test_gi_ghashtable_utf8_container_return: + * Returns: (element-type utf8 utf8) (transfer container): + */ +GHashTable * +test_gi_ghashtable_utf8_container_return (void) +{ + GHashTable *hash_table = NULL; + + hash_table = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(hash_table, "-1", "1"); + g_hash_table_insert(hash_table, "0", "0"); + g_hash_table_insert(hash_table, "1", "-1"); + g_hash_table_insert(hash_table, "2", "-2"); + + return hash_table; +} + +/** + * test_gi_ghashtable_utf8_full_return: + * Returns: (element-type utf8 utf8) (transfer full): + */ +GHashTable * +test_gi_ghashtable_utf8_full_return (void) +{ + GHashTable *hash_table = NULL; + + hash_table = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(hash_table, g_strdup("-1"), g_strdup("1")); + g_hash_table_insert(hash_table, g_strdup("0"), g_strdup("0")); + g_hash_table_insert(hash_table, g_strdup("1"), g_strdup("-1")); + g_hash_table_insert(hash_table, g_strdup("2"), g_strdup("-2")); + + return hash_table; +} + +/** + * test_gi_ghashtable_int_none_in: + * @hash_table: (element-type gint gint) (transfer none): + */ +void +test_gi_ghashtable_int_none_in (GHashTable *hash_table) +{ + g_assert(GPOINTER_TO_INT(g_hash_table_lookup(hash_table, GINT_TO_POINTER(-1))) == 1); + g_assert(GPOINTER_TO_INT(g_hash_table_lookup(hash_table, GINT_TO_POINTER(0))) == 0); + g_assert(GPOINTER_TO_INT(g_hash_table_lookup(hash_table, GINT_TO_POINTER(1))) == -1); + g_assert(GPOINTER_TO_INT(g_hash_table_lookup(hash_table, GINT_TO_POINTER(2))) == -2); +} + +/** + * test_gi_ghashtable_utf8_none_in: + * @hash_table: (element-type utf8 utf8) (transfer none): + */ +void +test_gi_ghashtable_utf8_none_in (GHashTable *hash_table) +{ + g_assert(strcmp(g_hash_table_lookup(hash_table, "-1"), "1") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "0"), "0") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "1"), "-1") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "2"), "-2") == 0); +} + +/** + * test_gi_ghashtable_utf8_container_in: + * @hash_table: (element-type utf8 utf8) (transfer container): + */ +void +test_gi_ghashtable_utf8_container_in (GHashTable *hash_table) +{ + g_assert(strcmp(g_hash_table_lookup(hash_table, "-1"), "1") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "0"), "0") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "1"), "-1") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "2"), "-2") == 0); + g_hash_table_steal_all(hash_table); + g_hash_table_unref(hash_table); +} + +/** + * test_gi_ghashtable_utf8_full_in: + * @hash_table: (element-type utf8 utf8) (transfer full): + */ +void +test_gi_ghashtable_utf8_full_in (GHashTable *hash_table) +{ + GHashTableIter hash_table_iter; + gpointer key, value; + + g_assert(strcmp(g_hash_table_lookup(hash_table, "-1"), "1") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "0"), "0") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "1"), "-1") == 0); + g_assert(strcmp(g_hash_table_lookup(hash_table, "2"), "-2") == 0); + + g_hash_table_iter_init(&hash_table_iter, hash_table); + while (g_hash_table_iter_next(&hash_table_iter, &key, &value)) { + g_free(key); + g_free(value); + g_hash_table_iter_steal(&hash_table_iter); + } + + g_hash_table_unref(hash_table); +} + +/** + * test_gi_ghashtable_utf8_none_out: + * @hash_table: (out) (element-type utf8 utf8) (transfer none): + */ +void +test_gi_ghashtable_utf8_none_out (GHashTable **hash_table) +{ + static GHashTable *new_hash_table = NULL; + + if (new_hash_table == NULL) { + new_hash_table = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(new_hash_table, "-1", "1"); + g_hash_table_insert(new_hash_table, "0", "0"); + g_hash_table_insert(new_hash_table, "1", "-1"); + g_hash_table_insert(new_hash_table, "2", "-2"); + } + + *hash_table = new_hash_table; +} + +/** + * test_gi_ghashtable_utf8_container_out: + * @hash_table: (out) (element-type utf8 utf8) (transfer container): + */ +void +test_gi_ghashtable_utf8_container_out (GHashTable **hash_table) +{ + *hash_table = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(*hash_table, "-1", "1"); + g_hash_table_insert(*hash_table, "0", "0"); + g_hash_table_insert(*hash_table, "1", "-1"); + g_hash_table_insert(*hash_table, "2", "-2"); +} + +/** + * test_gi_ghashtable_utf8_full_out: + * @hash_table: (out) (element-type utf8 utf8) (transfer full): + */ +void +test_gi_ghashtable_utf8_full_out (GHashTable **hash_table) +{ + *hash_table = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(*hash_table, g_strdup("-1"), g_strdup("1")); + g_hash_table_insert(*hash_table, g_strdup("0"), g_strdup("0")); + g_hash_table_insert(*hash_table, g_strdup("1"), g_strdup("-1")); + g_hash_table_insert(*hash_table, g_strdup("2"), g_strdup("-2")); +} + +/** + * test_gi_ghashtable_utf8_none_inout: + * @hash_table: (inout) (element-type utf8 utf8) (transfer none): + */ +void +test_gi_ghashtable_utf8_none_inout (GHashTable **hash_table) +{ + static GHashTable *new_hash_table = NULL; + + g_assert(strcmp(g_hash_table_lookup(*hash_table, "-1"), "1") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "0"), "0") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "1"), "-1") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "2"), "-2") == 0); + + if (new_hash_table == NULL) { + new_hash_table = g_hash_table_new(g_str_hash, g_str_equal); + g_hash_table_insert(new_hash_table, "-1", "1"); + g_hash_table_insert(new_hash_table, "0", "0"); + g_hash_table_insert(new_hash_table, "1", "1"); + } + + *hash_table = new_hash_table; +} + +/** + * test_gi_ghashtable_utf8_container_inout: + * @hash_table: (inout) (element-type utf8 utf8) (transfer container): + */ +void +test_gi_ghashtable_utf8_container_inout (GHashTable **hash_table) +{ + g_assert(strcmp(g_hash_table_lookup(*hash_table, "-1"), "1") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "0"), "0") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "1"), "-1") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "2"), "-2") == 0); + + g_hash_table_steal(*hash_table, "2"); + g_hash_table_steal(*hash_table, "1"); + g_hash_table_insert(*hash_table, "1", "1"); +} + +/** + * test_gi_ghashtable_utf8_full_inout: + * @hash_table: (inout) (element-type utf8 utf8) (transfer full): + */ +void +test_gi_ghashtable_utf8_full_inout (GHashTable **hash_table) +{ + g_assert(strcmp(g_hash_table_lookup(*hash_table, "-1"), "1") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "0"), "0") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "1"), "-1") == 0); + g_assert(strcmp(g_hash_table_lookup(*hash_table, "2"), "-2") == 0); + + g_hash_table_steal(*hash_table, "2"); + g_hash_table_steal(*hash_table, "1"); + g_hash_table_insert(*hash_table, "1", g_strdup("1")); +} + + +/** + * test_gi_gvalue_return: + * Returns: (transfer none): + */ +GValue * +test_gi_gvalue_return (void) +{ + static GValue *value = NULL; + + if (value == NULL) { + value = g_new0(GValue, 1); + g_value_init(value, G_TYPE_INT); + g_value_set_int(value, 42); + } + + return value; +} + +/** + * test_gi_gvalue_in: + * @value: (transfer none): + */ +void +test_gi_gvalue_in (GValue *value) +{ + g_assert(g_value_get_int(value) == 42); +} + +/** + * test_gi_gvalue_out: + * @value: (out) (transfer none): + */ +void +test_gi_gvalue_out (GValue **value) +{ + static GValue *new_value = NULL; + + if (new_value == NULL) { + new_value = g_new0(GValue, 1); + g_value_init(new_value, G_TYPE_INT); + g_value_set_int(new_value, 42); + } + + *value = new_value; +} + +/** + * test_gi_gvalue_inout: + * @value: (inout) (transfer none): + */ +void +test_gi_gvalue_inout (GValue **value) +{ + g_assert(g_value_get_int(*value) == 42); + g_value_unset(*value); + g_value_init(*value, G_TYPE_STRING); + g_value_set_string(*value, "42"); +} + + +/** + * test_gi_gclosure_in: + * @closure: (transfer none): + */ +void +test_gi_gclosure_in (GClosure *closure) +{ + GValue return_value = {0, }; + + g_value_init (&return_value, G_TYPE_INT); + + g_closure_invoke (closure, + &return_value, + 0, NULL, + NULL); + + g_assert(g_value_get_int (&return_value) == 42); + + g_value_unset(&return_value); +} + + +GType +test_gi_enum_get_type (void) +{ + static GType type = 0; + if (G_UNLIKELY(type == 0)) { + static const GEnumValue values[] = { + { TESTGI_ENUM_VALUE1, "TESTGI_ENUM_VALUE1", "value1" }, + { TESTGI_ENUM_VALUE2, "TESTGI_ENUM_VALUE2", "value2" }, + { TESTGI_ENUM_VALUE3, "TESTGI_ENUM_VALUE3", "value3" }, + { 0, NULL, NULL } + }; + type = g_enum_register_static (g_intern_static_string ("TestGIEnum"), values); + } + + return type; +} + +TestGIEnum +test_gi_enum_return (void) +{ + return TESTGI_ENUM_VALUE3; +} + +void +test_gi_enum_in (TestGIEnum enum_) +{ + g_assert(enum_ == TESTGI_ENUM_VALUE3); +} + +/** + * test_gi_enum_in_ptr: + * @enum_: (in) (transfer none): + */ +void +test_gi_enum_in_ptr (TestGIEnum *enum_) +{ + g_assert(*enum_ == TESTGI_ENUM_VALUE3); +} + +/** + * test_gi_enum_out: + * @enum_: (out): + */ +void +test_gi_enum_out (TestGIEnum *enum_) +{ + *enum_ = TESTGI_ENUM_VALUE3; +} + +/** + * test_gi_enum_inout: + * @enum_: (inout): + */ +void +test_gi_enum_inout (TestGIEnum *enum_) +{ + g_assert(*enum_ == TESTGI_ENUM_VALUE3); + *enum_ = TESTGI_ENUM_VALUE1; +} + + +GType +test_gi_flags_get_type (void) +{ + static GType type = 0; + if (G_UNLIKELY(type == 0)) { + static const GFlagsValue values[] = { + { TESTGI_FLAGS_VALUE1, "TESTGI_FLAGS_VALUE1", "value1" }, + { TESTGI_FLAGS_VALUE2, "TESTGI_FLAGS_VALUE2", "value2" }, + { TESTGI_FLAGS_VALUE3, "TESTGI_FLAGS_VALUE3", "value3" }, + { 0, NULL, NULL } + }; + type = g_flags_register_static (g_intern_static_string ("TestGIFlags"), values); + } + + return type; +} + +TestGIFlags +test_gi_flags_return (void) +{ + return TESTGI_FLAGS_VALUE2; +} + +void +test_gi_flags_in (TestGIFlags flags_) +{ + g_assert(flags_ == TESTGI_FLAGS_VALUE2); +} + +/** + * test_gi_flags_in_ptr: + * @flags_: (in) (transfer none): + */ +void +test_gi_flags_in_ptr (TestGIFlags *flags_) +{ + g_assert(*flags_ == TESTGI_FLAGS_VALUE2); +} + +/** + * test_gi_flags_out: + * @flags_: (out): + */ +void +test_gi_flags_out (TestGIFlags *flags_) +{ + *flags_ = TESTGI_FLAGS_VALUE2; +} + +/** + * test_gi_flags_inout: + * @flags_: (inout): + */ +void +test_gi_flags_inout (TestGIFlags *flags_) +{ + g_assert(*flags_ == TESTGI_FLAGS_VALUE2); + *flags_ = TESTGI_FLAGS_VALUE1; +} + + +/** + * test_gi__simple_struct_return: + * Returns: (transfer none): + */ +TestGISimpleStruct * +test_gi__simple_struct_return (void) +{ + static TestGISimpleStruct *struct_ = NULL; + + if (struct_ == NULL) { + struct_ = g_new(TestGISimpleStruct, 1); + + struct_->long_ = 6; + struct_->int8 = 7; + } + + return struct_; +} + +/** + * test_gi__simple_struct_in: + * @struct_: (transfer none): + */ +void +test_gi__simple_struct_in (TestGISimpleStruct *struct_) +{ + g_assert(struct_->long_ == 6); + g_assert(struct_->int8 == 7); +} + +/** + * test_gi__simple_struct_out: + * @struct_: (out) (transfer none): + */ +void +test_gi__simple_struct_out (TestGISimpleStruct **struct_) +{ + static TestGISimpleStruct *new_struct = NULL; + + if (new_struct == NULL) { + new_struct = g_new(TestGISimpleStruct, 1); + + new_struct->long_ = 6; + new_struct->int8 = 7; + } + + *struct_ = new_struct; +} + +/** + * test_gi__simple_struct_inout: + * @struct_: (inout) (transfer none): + */ +void +test_gi__simple_struct_inout (TestGISimpleStruct **struct_) +{ + g_assert((*struct_)->long_ == 6); + g_assert((*struct_)->int8 == 7); + + (*struct_)->long_ = 7; + (*struct_)->int8 = 6; +} + +void +test_gi_simple_struct_method (TestGISimpleStruct *struct_) +{ + g_assert(struct_->long_ == 6); + g_assert(struct_->int8 == 7); +} + + +GType +test_gi_pointer_struct_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_pointer_type_register_static ("TestGIPointerStruct"); + } + + return type; +} + +/** + * test_gi__pointer_struct_return: + * Returns: (transfer none): + */ +TestGIPointerStruct * +test_gi__pointer_struct_return (void) +{ + static TestGIPointerStruct *struct_ = NULL; + + if (struct_ == NULL) { + struct_ = g_new(TestGIPointerStruct, 1); + + struct_->long_ = 42; + } + + return struct_; +} + +/** + * test_gi__pointer_struct_in: + * @struct_: (transfer none): + */ +void +test_gi__pointer_struct_in (TestGIPointerStruct *struct_) +{ + g_assert(struct_->long_ == 42); +} + +/** + * test_gi__pointer_struct_out: + * @struct_: (out) (transfer none): + */ +void +test_gi__pointer_struct_out (TestGIPointerStruct **struct_) +{ + static TestGIPointerStruct *new_struct = NULL; + + if (new_struct == NULL) { + new_struct = g_new(TestGIPointerStruct, 1); + + new_struct->long_ = 42; + } + + *struct_ = new_struct; +} + +/** + * test_gi__pointer_struct_inout: + * @struct_: (inout) (transfer none): + */ +void +test_gi__pointer_struct_inout (TestGIPointerStruct **struct_) +{ + g_assert((*struct_)->long_ == 42); + + (*struct_)->long_ = 0; +} + + +TestGIBoxedStruct * +test_gi_boxed_struct_copy (TestGIBoxedStruct *struct_) +{ + TestGIBoxedStruct *new_struct; + + new_struct = g_slice_new (TestGIBoxedStruct); + + *new_struct = *struct_; + + return new_struct; +} + +static void +test_gi_boxed_struct_free (TestGIBoxedStruct *struct_) +{ + g_slice_free (TestGIBoxedStruct, struct_); +} + +GType +test_gi_boxed_struct_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static ("TestGIBoxedStruct", + (GBoxedCopyFunc) test_gi_boxed_struct_copy, + (GBoxedFreeFunc) test_gi_boxed_struct_free); + } + + return type; +} + + +TestGIBoxedInstantiableStruct * +test_gi_boxed_instantiable_struct_copy (TestGIBoxedInstantiableStruct *struct_) +{ + TestGIBoxedInstantiableStruct *new_struct; + + new_struct = g_slice_new (TestGIBoxedInstantiableStruct); + + *new_struct = *struct_; + + return new_struct; +} + +static void +test_gi_boxed_instantiable_struct_free (TestGIBoxedInstantiableStruct *struct_) +{ + g_slice_free (TestGIBoxedInstantiableStruct, struct_); +} + +GType +test_gi_boxed_instantiable_struct_get_type (void) +{ + static GType type = 0; + + if (type == 0) { + type = g_boxed_type_register_static ("TestGIBoxedInstantiableStruct", + (GBoxedCopyFunc) test_gi_boxed_instantiable_struct_copy, + (GBoxedFreeFunc) test_gi_boxed_instantiable_struct_free); + } + + return type; +} + +TestGIBoxedInstantiableStruct * +test_gi_boxed_instantiable_struct_new (void) +{ + return g_slice_new (TestGIBoxedInstantiableStruct); +} + +/** + * test_gi__boxed_instantiable_struct_return: + * Returns: (transfer none): + */ +TestGIBoxedInstantiableStruct * +test_gi__boxed_instantiable_struct_return (void) +{ + static TestGIBoxedInstantiableStruct *struct_ = NULL; + + if (struct_ == NULL) { + struct_ = g_new(TestGIBoxedInstantiableStruct, 1); + + struct_->long_ = 42; + } + + return struct_; +} + +/** + * test_gi__boxed_instantiable_struct_in: + * @struct_: (transfer none): + */ +void +test_gi__boxed_instantiable_struct_in (TestGIBoxedInstantiableStruct *struct_) +{ + g_assert(struct_->long_ == 42); +} + +/** + * test_gi__boxed_instantiable_struct_out: + * @struct_: (out) (transfer none): + */ +void +test_gi__boxed_instantiable_struct_out (TestGIBoxedInstantiableStruct **struct_) +{ + static TestGIBoxedInstantiableStruct *new_struct = NULL; + + if (new_struct == NULL) { + new_struct = g_new(TestGIBoxedInstantiableStruct, 1); + + new_struct->long_ = 42; + } + + *struct_ = new_struct; +} + +/** + * test_gi__boxed_instantiable_struct_inout: + * @struct_: (inout) (transfer none): + */ +void +test_gi__boxed_instantiable_struct_inout (TestGIBoxedInstantiableStruct **struct_) +{ + g_assert((*struct_)->long_ == 42); + + (*struct_)->long_ = 0; +} + + +enum +{ + PROP_0, + PROP_INT_ +}; + +G_DEFINE_TYPE (TestGIObject, test_gi_object, G_TYPE_OBJECT); + +static void +test_gi_object_init (TestGIObject *object) +{ +} + +static void +test_gi_object_finalize (GObject *object) +{ + G_OBJECT_CLASS (test_gi_object_parent_class)->finalize (object); +} + +static void +test_gi_object_set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec) +{ + g_return_if_fail (TESTGI_IS_OBJECT (object)); + + switch (prop_id) { + case PROP_INT_: + TESTGI_OBJECT (object)->int_ = g_value_get_int (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +test_gi_object_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec) +{ + g_return_if_fail (TESTGI_IS_OBJECT (object)); + + switch (prop_id) { + case PROP_INT_: + g_value_set_int (value, TESTGI_OBJECT (object)->int_); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +test_gi_object_class_init (TestGIObjectClass *klass) +{ + GObjectClass* object_class = G_OBJECT_CLASS (klass); +#if 0 + GObjectClass* parent_class = G_OBJECT_CLASS (klass); +#endif + + object_class->finalize = test_gi_object_finalize; + object_class->set_property = test_gi_object_set_property; + object_class->get_property = test_gi_object_get_property; + + g_object_class_install_property (object_class, PROP_INT_, + g_param_spec_int ("int", "Integer", "An integer", G_MININT, G_MAXINT, 0, + G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT)); +} + + +void +test_gi_object_static_method (void) +{ +} + +void +test_gi_object_method (TestGIObject *object) +{ + g_return_if_fail (TESTGI_IS_OBJECT (object)); + g_assert (object->int_ == 42); +} + +void +test_gi_object_overridden_method (TestGIObject *object) +{ + g_return_if_fail (TESTGI_IS_OBJECT (object)); + g_assert (object->int_ == 0); +} + +TestGIObject * +test_gi_object_new (gint int_) +{ + return g_object_new (TESTGI_TYPE_OBJECT, "int", int_, NULL); +} + + +/** + * test_gi__object_none_return: + * Returns: (transfer none): + */ +TestGIObject * +test_gi__object_none_return (void) +{ + static TestGIObject *object = NULL; + + if (object == NULL) { + object = g_object_new(TESTGI_TYPE_OBJECT, NULL); + } + + return object; +} + +/** + * test_gi__object_full_return: + * Returns: (transfer full): + */ +TestGIObject * +test_gi__object_full_return (void) +{ + return g_object_new(TESTGI_TYPE_OBJECT, NULL); +} + +/** + * test_gi__object_none_in: + * @object: (transfer none): + */ +void +test_gi__object_none_in (TestGIObject *object) +{ + g_assert(object->int_ == 42); +} + +/** + * test_gi__object_full_in: + * @object: (transfer full): + */ +void +test_gi__object_full_in (TestGIObject *object) +{ + g_assert(object->int_ == 42); + g_object_unref(object); +} + +/** + * test_gi__object_none_out: + * @object: (out) (transfer none): + */ +void +test_gi__object_none_out (TestGIObject **object) +{ + static TestGIObject *new_object = NULL; + + if (new_object == NULL) { + new_object = g_object_new(TESTGI_TYPE_OBJECT, NULL); + } + + *object = new_object; +} + +/** + * test_gi__object_full_out: + * @object: (out) (transfer full): + */ +void +test_gi__object_full_out (TestGIObject **object) +{ + *object = g_object_new(TESTGI_TYPE_OBJECT, NULL); +} + +/** + * test_gi__object_none_inout: + * @object: (inout) (transfer none): + */ +void +test_gi__object_none_inout (TestGIObject **object) +{ + static TestGIObject *new_object = NULL; + + g_assert((*object)->int_ == 42); + + if (new_object == NULL) { + new_object = g_object_new(TESTGI_TYPE_OBJECT, NULL); + new_object->int_ = 0; + } + + *object = new_object; +} + +/** + * test_gi__object_full_inout: + * @object: (inout) (transfer full): + */ +void +test_gi__object_full_inout (TestGIObject **object) +{ + g_assert((*object)->int_ == 42); + g_object_unref(*object); + + *object = g_object_new(TESTGI_TYPE_OBJECT, NULL); +} + +/** + * test_gi__object_inout_same: + * @object: (inout): + */ +void +test_gi__object_inout_same (TestGIObject **object) +{ + g_assert((*object)->int_ == 42); + (*object)->int_ = 0; +} + + +G_DEFINE_TYPE (TestGISubObject, test_gi_sub_object, TESTGI_TYPE_OBJECT); + +static void +test_gi_sub_object_init (TestGISubObject *object) +{ +} + +static void +test_gi_sub_object_finalize (GObject *object) +{ + G_OBJECT_CLASS(test_gi_sub_object_parent_class)->finalize(object); +} + +static void +test_gi_sub_object_class_init (TestGISubObjectClass *klass) +{ + G_OBJECT_CLASS(klass)->finalize = test_gi_sub_object_finalize; +} + +void +test_gi_sub_object_sub_method (TestGISubObject *object) +{ + g_assert(TESTGI_OBJECT(object)->int_ == 0); +} + +void +test_gi_sub_object_overwritten_method (TestGISubObject *object) +{ + g_assert(TESTGI_OBJECT(object)->int_ == 0); +} + +/** + * test_gi_int_out_out: + * int0: (out): + * int1: (out): + */ +void +test_gi_int_out_out (gint *int0, gint *int1) +{ + *int0 = 6; + *int1 = 7; +} + +/** + * test_gi_int_return_out: + * int_: (out): + */ +gint +test_gi_int_return_out (gint *int_) +{ + *int_ = 7; + return 6; +} + +/** + * test_gi_ptr_return_null: + * Returns: (allow-none): + */ +gint * +test_gi_int_return_ptr_null (void) +{ + return NULL; +} + diff --git a/tests/libtestgi.h b/tests/libtestgi.h new file mode 100644 index 00000000..9fbdbbd6 --- /dev/null +++ b/tests/libtestgi.h @@ -0,0 +1,643 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + */ + +#include + +#ifndef __TEST_GI_H__ +#define __TEST_GI_H__ + + +/* Constants */ + +#define TESTGI_CONSTANT_NUMBER 42 +#define TESTGI_CONSTANT_UTF8 "const \xe2\x99\xa5 utf8" + + +/* Booleans */ + +gboolean test_gi_boolean_return_true (void); +gboolean test_gi_boolean_return_false (void); + +gboolean *test_gi_boolean_return_ptr_true (void); +gboolean *test_gi_boolean_return_ptr_false (void); + +void test_gi_boolean_in_true (gboolean bool_); +void test_gi_boolean_in_false (gboolean bool_); + +void test_gi_boolean_out_true (gboolean *bool_); +void test_gi_boolean_out_false (gboolean *bool_); + +void test_gi_boolean_inout_true_false (gboolean *bool_); +void test_gi_boolean_inout_false_true (gboolean *bool_); + +void test_gi_boolean_in_ptr_true (gboolean *bool_); +void test_gi_boolean_in_ptr_false (gboolean *bool_); + + +/* Integers */ + +gint8 test_gi_int8_return_max (void); +gint8 test_gi_int8_return_min (void); + +gint8 *test_gi_int8_return_ptr_max (void); +gint8 *test_gi_int8_return_ptr_min (void); + +void test_gi_int8_in_max (gint8 int8); +void test_gi_int8_in_min (gint8 int8); + +void test_gi_int8_in_ptr_max (gint8 *int8); +void test_gi_int8_in_ptr_min (gint8 *int8); + +void test_gi_int8_out_max (gint8 *int8); +void test_gi_int8_out_min (gint8 *int8); + +void test_gi_int8_inout_max_min (gint8 *int8); +void test_gi_int8_inout_min_max (gint8 *int8); + + +guint8 test_gi_uint8_return (void); +guint8 *test_gi_uint8_return_ptr (void); + +void test_gi_uint8_in (guint8 uint8); +void test_gi_uint8_in_ptr (guint8 *uint8); + +void test_gi_uint8_out (guint8 *uint8); +void test_gi_uint8_inout (guint8 *uint8); + + +gint16 test_gi_int16_return_max (void); +gint16 test_gi_int16_return_min (void); + +gint16 *test_gi_int16_return_ptr_max (void); +gint16 *test_gi_int16_return_ptr_min (void); + +void test_gi_int16_in_max (gint16 int16); +void test_gi_int16_in_min (gint16 int16); + +void test_gi_int16_in_ptr_max (gint16 *int16); +void test_gi_int16_in_ptr_min (gint16 *int16); + +void test_gi_int16_out_max (gint16 *int16); +void test_gi_int16_out_min (gint16 *int16); + +void test_gi_int16_inout_max_min (gint16 *int16); +void test_gi_int16_inout_min_max (gint16 *int16); + + +guint16 test_gi_uint16_return (void); +guint16 *test_gi_uint16_return_ptr (void); + +void test_gi_uint16_in (guint16 uint16); +void test_gi_uint16_in_ptr (guint16 *uint16); + +void test_gi_uint16_out (guint16 *uint16); +void test_gi_uint16_inout (guint16 *uint16); + + +gint32 test_gi_int32_return_max (void); +gint32 test_gi_int32_return_min (void); + +gint32 *test_gi_int32_return_ptr_max (void); +gint32 *test_gi_int32_return_ptr_min (void); + +void test_gi_int32_in_max (gint32 int32); +void test_gi_int32_in_min (gint32 int32); + +void test_gi_int32_in_ptr_max (gint32 *int32); +void test_gi_int32_in_ptr_min (gint32 *int32); + +void test_gi_int32_out_max (gint32 *int32); +void test_gi_int32_out_min (gint32 *int32); + +void test_gi_int32_inout_max_min (gint32 *int32); +void test_gi_int32_inout_min_max (gint32 *int32); + + +guint32 test_gi_uint32_return (void); +guint32 *test_gi_uint32_return_ptr (void); + +void test_gi_uint32_in (guint32 uint32); +void test_gi_uint32_in_ptr (guint32 *uint32); + +void test_gi_uint32_out (guint32 *uint32); +void test_gi_uint32_inout (guint32 *uint32); + + +gint64 test_gi_int64_return_max (void); +gint64 test_gi_int64_return_min (void); + +gint64 *test_gi_int64_return_ptr_max (void); +gint64 *test_gi_int64_return_ptr_min (void); + +void test_gi_int64_in_max (gint64 int64); +void test_gi_int64_in_min (gint64 int64); + +void test_gi_int64_in_ptr_max (gint64 *int64); +void test_gi_int64_in_ptr_min (gint64 *int64); + +void test_gi_int64_out_max (gint64 *int64); +void test_gi_int64_out_min (gint64 *int64); + +void test_gi_int64_inout_max_min (gint64 *int64); +void test_gi_int64_inout_min_max (gint64 *int64); + + +guint64 test_gi_uint64_return (void); +guint64 *test_gi_uint64_return_ptr (void); + +void test_gi_uint64_in (guint64 uint64); +void test_gi_uint64_in_ptr (guint64 *uint64); + +void test_gi_uint64_out (guint64 *uint64); +void test_gi_uint64_inout (guint64 *uint64); + + +gshort test_gi_short_return_max (void); +gshort test_gi_short_return_min (void); + +gshort *test_gi_short_return_ptr_max (void); +gshort *test_gi_short_return_ptr_min (void); + +void test_gi_short_in_max (gshort short_); +void test_gi_short_in_min (gshort short_); + +void test_gi_short_in_ptr_max (gshort *short_); +void test_gi_short_in_ptr_min (gshort *short_); + +void test_gi_short_out_max (gshort *short_); +void test_gi_short_out_min (gshort *short_); + +void test_gi_short_inout_max_min (gshort *short_); +void test_gi_short_inout_min_max (gshort *short_); + + +gushort test_gi_ushort_return (void); +gushort *test_gi_ushort_return_ptr (void); + +void test_gi_ushort_in (gushort ushort); +void test_gi_ushort_in_ptr (gushort *ushort); + +void test_gi_ushort_out (gushort *ushort); +void test_gi_ushort_inout (gushort *ushort); + + +gint test_gi_int_return_max (void); +gint test_gi_int_return_min (void); + +gint *test_gi_int_return_ptr_max (void); +gint *test_gi_int_return_ptr_min (void); + +void test_gi_int_in_max (gint int_); +void test_gi_int_in_min (gint int_); + +void test_gi_int_in_ptr_max (gint *int_); +void test_gi_int_in_ptr_min (gint *int_); + +void test_gi_int_out_max (gint *int_); +void test_gi_int_out_min (gint *int_); + +void test_gi_int_inout_max_min (gint *int_); +void test_gi_int_inout_min_max (gint *int_); + + +guint test_gi_uint_return (void); +guint *test_gi_uint_return_ptr (void); + +void test_gi_uint_in (guint uint); +void test_gi_uint_in_ptr (guint *uint); + +void test_gi_uint_out (guint *uint); +void test_gi_uint_inout (guint *uint); + + +glong test_gi_long_return_max (void); +glong test_gi_long_return_min (void); + +glong *test_gi_long_return_ptr_max (void); +glong *test_gi_long_return_ptr_min (void); + +void test_gi_long_in_max (glong long_); +void test_gi_long_in_min (glong long_); + +void test_gi_long_in_ptr_max (glong *long_); +void test_gi_long_in_ptr_min (glong *long_); + +void test_gi_long_out_max (glong *long_); +void test_gi_long_out_min (glong *long_); + +void test_gi_long_inout_max_min (glong *long_); +void test_gi_long_inout_min_max (glong *long_); + + +gulong test_gi_ulong_return (void); +gulong *test_gi_ulong_return_ptr (void); + +void test_gi_ulong_in (gulong ulong); +void test_gi_ulong_in_ptr (gulong *ulong); + +void test_gi_ulong_out (gulong *ulong); +void test_gi_ulong_inout (gulong *ulong); + + +gssize test_gi_ssize_return_max (void); +gssize test_gi_ssize_return_min (void); + +gssize *test_gi_ssize_return_ptr_max (void); +gssize *test_gi_ssize_return_ptr_min (void); + +void test_gi_ssize_in_max (gssize ssize); +void test_gi_ssize_in_min (gssize ssize); + +void test_gi_ssize_in_ptr_max (gssize *ssize); +void test_gi_ssize_in_ptr_min (gssize *ssize); + +void test_gi_ssize_out_max (gssize *ssize); +void test_gi_ssize_out_min (gssize *ssize); + +void test_gi_ssize_inout_max_min (gssize *ssize); +void test_gi_ssize_inout_min_max (gssize *ssize); + + +gsize test_gi_size_return (void); +gsize *test_gi_size_return_ptr (void); + +void test_gi_size_in (gsize size); +void test_gi_size_in_ptr (gsize *size); + +void test_gi_size_out (gsize *size); +void test_gi_size_inout (gsize *size); + + +/* Floating-point */ + +gfloat test_gi_float_return (void); +gfloat *test_gi_float_return_ptr (void); + +void test_gi_float_in (gfloat float_); +void test_gi_float_in_ptr (gfloat *float_); + +void test_gi_float_out (gfloat *float_); + +void test_gi_float_inout (gfloat *float_); + + +gdouble test_gi_double_return (void); +gdouble *test_gi_double_return_ptr (void); + +void test_gi_double_in (gdouble double_); +void test_gi_double_in_ptr (gdouble *double_); + +void test_gi_double_out (gdouble *double_); + +void test_gi_double_inout (gdouble *double_); + + +/* Timestamps */ + +time_t test_gi_time_t_return (void); +time_t *test_gi_time_t_return_ptr (void); + +void test_gi_time_t_in (time_t time_t_); +void test_gi_time_t_in_ptr (time_t *time_t_); + +void test_gi_time_t_out (time_t *time_t_); + +void test_gi_time_t_inout (time_t *time_t_); + + +/* GType */ + +GType test_gi_gtype_return (void); +GType *test_gi_gtype_return_ptr (void); + +void test_gi_gtype_in (GType gtype); +void test_gi_gtype_in_ptr (GType *gtype); + +void test_gi_gtype_out (GType *gtype); + +void test_gi_gtype_inout (GType *gtype); + + +/* UTF-8 */ + +const gchar *test_gi_utf8_none_return (void); +gchar *test_gi_utf8_full_return (void); + +void test_gi_utf8_none_in (const gchar *utf8); +void test_gi_utf8_full_in (gchar *utf8); + +void test_gi_utf8_none_out (gchar **utf8); +void test_gi_utf8_full_out (gchar **utf8); + +void test_gi_utf8_none_inout (gchar **utf8); +void test_gi_utf8_full_inout (gchar **utf8); + + +/* Arrays */ + +/* Fixed-size */ +const gint *test_gi_array_fixed_int_return (void); +const gshort *test_gi_array_fixed_short_return (void); + +void test_gi_array_fixed_int_in (const gint *ints); +void test_gi_array_fixed_short_in (const gshort *shorts); + +void test_gi_array_fixed_out (gint **ints); + +void test_gi_array_fixed_inout (gint **ints); + +/* Variable-size */ + +const gint *test_gi_array_return (gint *length); + +void test_gi_array_in (const gint *ints, gint length); + +void test_gi_array_out (gint **ints, gint *length); + +void test_gi_array_inout (gint **ints, gint *length); + +/* Zero-terminated */ + +gchar **test_gi_array_zero_terminated_return (void); + +void test_gi_array_zero_terminated_in (gchar **utf8s); + +void test_gi_array_zero_terminated_out (gchar ***utf8s); + +void test_gi_array_zero_terminated_inout (gchar ***utf8s); + + +/* GList */ + +GList *test_gi_glist_int_none_return (void); +GList *test_gi_glist_utf8_none_return (void); +GList *test_gi_glist_utf8_container_return (void); +GList *test_gi_glist_utf8_full_return (void); + +void test_gi_glist_int_none_in (GList *list); +void test_gi_glist_utf8_none_in (GList *list); +void test_gi_glist_utf8_container_in (GList *list); +void test_gi_glist_utf8_full_in (GList *list); + +void test_gi_glist_utf8_none_out (GList **list); +void test_gi_glist_utf8_container_out (GList **list); +void test_gi_glist_utf8_full_out (GList **list); + +void test_gi_glist_utf8_none_inout (GList **list); +void test_gi_glist_utf8_container_inout (GList **list); +void test_gi_glist_utf8_full_inout (GList **list); + + +/* GSList */ + +GSList *test_gi_gslist_int_none_return (void); +GSList *test_gi_gslist_utf8_none_return (void); +GSList *test_gi_gslist_utf8_container_return (void); +GSList *test_gi_gslist_utf8_full_return (void); + +void test_gi_gslist_int_none_in (GSList *list); +void test_gi_gslist_utf8_none_in (GSList *list); +void test_gi_gslist_utf8_container_in (GSList *list); +void test_gi_gslist_utf8_full_in (GSList *list); + +void test_gi_gslist_utf8_none_out (GSList **list); +void test_gi_gslist_utf8_container_out (GSList **list); +void test_gi_gslist_utf8_full_out (GSList **list); + +void test_gi_gslist_utf8_none_inout (GSList **list); +void test_gi_gslist_utf8_container_inout (GSList **list); +void test_gi_gslist_utf8_full_inout (GSList **list); + + +/* GHashTable */ + +GHashTable *test_gi_ghashtable_int_none_return (void); +GHashTable *test_gi_ghashtable_utf8_none_return (void); +GHashTable *test_gi_ghashtable_utf8_container_return (void); +GHashTable *test_gi_ghashtable_utf8_full_return (void); + +void test_gi_ghashtable_int_none_in (GHashTable *hash_table); +void test_gi_ghashtable_utf8_none_in (GHashTable *hash_table); +void test_gi_ghashtable_utf8_container_in (GHashTable *hash_table); +void test_gi_ghashtable_utf8_full_in (GHashTable *hash_table); + +void test_gi_ghashtable_utf8_none_out (GHashTable **hash_table); +void test_gi_ghashtable_utf8_container_out (GHashTable **hash_table); +void test_gi_ghashtable_utf8_full_out (GHashTable **hash_table); + +void test_gi_ghashtable_utf8_none_inout (GHashTable **hash_table); +void test_gi_ghashtable_utf8_container_inout (GHashTable **hash_table); +void test_gi_ghashtable_utf8_full_inout (GHashTable **hash_table); + + +/* GValue */ + +GValue *test_gi_gvalue_return (void); + +void test_gi_gvalue_in (GValue *value); + +void test_gi_gvalue_out (GValue **value); + +void test_gi_gvalue_inout (GValue **value); + + +/* GClosure */ + +void test_gi_gclosure_in (GClosure *closure); + + +/* GEnum */ + +typedef enum +{ + TESTGI_ENUM_VALUE1, + TESTGI_ENUM_VALUE2, + TESTGI_ENUM_VALUE3 = 42 +} TestGIEnum; + +GType test_gi_enum_get_type (void) G_GNUC_CONST; +#define TESTGI_TYPE_ENUM (test_gi_enum_get_type ()) + +TestGIEnum test_gi_enum_return (void); + +void test_gi_enum_in (TestGIEnum enum_); +void test_gi_enum_in_ptr (TestGIEnum *enum_); + +void test_gi_enum_out (TestGIEnum *enum_); + +void test_gi_enum_inout (TestGIEnum *enum_); + + +/* GFlags */ + +typedef enum +{ + TESTGI_FLAGS_VALUE1 = 1 << 0, + TESTGI_FLAGS_VALUE2 = 1 << 1, + TESTGI_FLAGS_VALUE3 = 1 << 2 +} TestGIFlags; + +GType test_gi_flags_get_type (void) G_GNUC_CONST; +#define TESTGI_TYPE_FLAGS (test_gi_flags_get_type ()) + +TestGIFlags test_gi_flags_return (void); + +void test_gi_flags_in (TestGIFlags flags_); +void test_gi_flags_in_ptr (TestGIFlags *flags_); + +void test_gi_flags_out (TestGIFlags *flags_); + +void test_gi_flags_inout (TestGIFlags *flags_); + + +/* Structure */ + +typedef struct { + glong long_; + gint8 int8; +} TestGISimpleStruct; + +typedef struct { + TestGISimpleStruct simple_struct; +} TestGINestedStruct; + +typedef struct { + gpointer pointer; +} TestGINotSimpleStruct; + + +TestGISimpleStruct *test_gi__simple_struct_return (void); + +void test_gi__simple_struct_in (TestGISimpleStruct *struct_); + +void test_gi__simple_struct_out (TestGISimpleStruct **struct_); + +void test_gi__simple_struct_inout (TestGISimpleStruct **struct_); + +void test_gi_simple_struct_method (TestGISimpleStruct *struct_); + + +typedef struct { + glong long_; +} TestGIPointerStruct; + +GType test_gi_pointer_struct_get_type (void) G_GNUC_CONST; + +TestGIPointerStruct *test_gi__pointer_struct_return (void); + +void test_gi__pointer_struct_in (TestGIPointerStruct *struct_); + +void test_gi__pointer_struct_out (TestGIPointerStruct **struct_); + +void test_gi__pointer_struct_inout (TestGIPointerStruct **struct_); + + +typedef struct { + glong long_; +} TestGIBoxedStruct; + +GType test_gi_boxed_struct_get_type (void) G_GNUC_CONST; + + +typedef struct { + glong long_; +} TestGIBoxedInstantiableStruct; + +GType test_gi_boxed_instantiable_struct_get_type (void) G_GNUC_CONST; + +TestGIBoxedInstantiableStruct *test_gi_boxed_instantiable_struct_new (void); + +TestGIBoxedInstantiableStruct *test_gi__boxed_instantiable_struct_return (void); + +void test_gi__boxed_instantiable_struct_in (TestGIBoxedInstantiableStruct *struct_); + +void test_gi__boxed_instantiable_struct_out (TestGIBoxedInstantiableStruct **struct_); + +void test_gi__boxed_instantiable_struct_inout (TestGIBoxedInstantiableStruct **struct_); + + +/* Object */ + +#define TESTGI_TYPE_OBJECT (test_gi_object_get_type ()) +#define TESTGI_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TESTGI_TYPE_OBJECT, TestGIObject)) +#define TESTGI_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TESTGI_TYPE_OBJECT, TestGIObjectClass)) +#define TESTGI_IS_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TESTGI_TYPE_OBJECT)) +#define TESTGI_IS_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TESTGI_TYPE_OBJECT)) +#define TESTGI_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TESTGI_TYPE_OBJECT, TestGIObjectClass)) + +typedef struct _TestGIObjectClass TestGIObjectClass; +typedef struct _TestGIObject TestGIObject; + +struct _TestGIObjectClass +{ + GObjectClass parent_class; +}; + +struct _TestGIObject +{ + GObject parent_instance; + + gint int_; +}; + +GType test_gi_object_get_type (void) G_GNUC_CONST; +void test_gi_object_static_method (void); +void test_gi_object_method (TestGIObject *object); +void test_gi_object_overridden_method (TestGIObject *object); +TestGIObject *test_gi_object_new (gint int_); + + +TestGIObject *test_gi__object_none_return (void); +TestGIObject *test_gi__object_full_return (void); + +void test_gi__object_none_in (TestGIObject *object); +void test_gi__object_full_in (TestGIObject *object); + +void test_gi__object_none_out (TestGIObject **object); +void test_gi__object_full_out (TestGIObject **object); + +void test_gi__object_none_inout (TestGIObject **object); +void test_gi__object_full_inout (TestGIObject **object); +void test_gi__object_inout_same (TestGIObject **object); + + +#define TESTGI_TYPE_SUB_OBJECT (test_gi_sub_object_get_type ()) +#define TESTGI_SUB_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TESTGI_TYPE_SUB_OBJECT, TestGISubObject)) +#define TESTGI_SUB_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TESTGI_TYPE_SUB_OBJECT, TestGISubObjectClass)) +#define TESTGI_IS_SUB_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TESTGI_TYPE_SUB_OBJECT)) +#define TESTGI_IS_SUB_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TESTGI_TYPE_SUB_OBJECT)) +#define TESTGI_SUB_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TESTGI_TYPE_SUB_OBJECT, TestGISubObjectClass)) + +typedef struct _TestGISubObjectClass TestGISubObjectClass; +typedef struct _TestGISubObject TestGISubObject; + +struct _TestGISubObjectClass +{ + TestGIObjectClass parent_class; +}; + +struct _TestGISubObject +{ + TestGIObject parent_instance; +}; + +GType test_gi_sub_object_get_type (void) G_GNUC_CONST; + +void test_gi_sub_object_sub_method (TestGISubObject *object); +void test_gi_sub_object_overwritten_method (TestGISubObject *object); + + +/* Multiple output arguments */ + +void test_gi_int_out_out (gint *int0, gint *int1); +gint test_gi_int_return_out (gint *int_); + + +/* Nullable arguments */ + +gint *test_gi_int_return_ptr_null (void); +void test_gi_int_in_ptr_null (gint *int_); + + +#endif /* __TEST_GI_H__ */ diff --git a/tests/runtests.py b/tests/runtests.py new file mode 100644 index 00000000..7ba5c422 --- /dev/null +++ b/tests/runtests.py @@ -0,0 +1,22 @@ +#!/usr/bin/env python + +import sys +import unittest +import glob + +sys.path.insert(0, "../") + +loader = unittest.TestLoader() + +if len(sys.argv) > 1: + names = sys.argv[1:] + suite = loader.loadTestsFromNames(names) +else: + names = [] + for filename in glob.iglob("test_*.py"): + names.append(filename[:-3]) + suite = loader.loadTestsFromNames(names) + +runner = unittest.TextTestRunner(verbosity=2) +runner.run(suite) + diff --git a/tests/test_gi.py b/tests/test_gi.py new file mode 100644 index 00000000..7c296150 --- /dev/null +++ b/tests/test_gi.py @@ -0,0 +1,1416 @@ +# -*- Mode: Python; py-indent-offset: 4 -*- +# vim: tabstop=4 shiftwidth=4 expandtab + +import unittest +import gobject + +from datetime import datetime + +from gi.repository import TestGI + + +CONSTANT_UTF8 = "const \xe2\x99\xa5 utf8" +CONSTANT_NUMBER = 42 + + +class Number(object): + + def __init__(self, value): + self.value = value + + def __int__(self): + return int(self.value) + + def __float__(self): + return float(self.value) + + +class Sequence(object): + + def __init__(self, sequence): + self.sequence = sequence + + def __len__(self): + return len(self.sequence) + + def __getitem__(self, key): + return self.sequence[key] + + +class TestConstant(unittest.TestCase): + +# Blocked by https://bugzilla.gnome.org/show_bug.cgi?id=595773 +# def test_constant_utf8(self): +# self.assertEquals(CONSTANT_UTF8, TestGI.CONSTANT_UTF8) + + def test_constant_number(self): + self.assertEquals(CONSTANT_NUMBER, TestGI.CONSTANT_NUMBER) + + +class TestBoolean(unittest.TestCase): + + def test_boolean_return(self): + self.assertEquals(True, TestGI.boolean_return_true()) + self.assertEquals(False, TestGI.boolean_return_false()) + + def test_boolean_return_ptr(self): + self.assertEquals(True, TestGI.boolean_return_ptr_true()) + self.assertEquals(False, TestGI.boolean_return_ptr_false()) + + def test_boolean_in(self): + TestGI.boolean_in_true(True) + TestGI.boolean_in_false(False) + + TestGI.boolean_in_true(1) + TestGI.boolean_in_false(0) + + def test_boolean_in_ptr(self): + TestGI.boolean_in_ptr_true(True) + TestGI.boolean_in_ptr_false(False) + TestGI.boolean_in_ptr_false(None) + + def test_boolean_out(self): + self.assertEquals(True, TestGI.boolean_out_true()) + self.assertEquals(False, TestGI.boolean_out_false()) + + def test_boolean_inout(self): + self.assertEquals(False, TestGI.boolean_inout_true_false(True)) + self.assertEquals(True, TestGI.boolean_inout_false_true(False)) + + +class TestInt8(unittest.TestCase): + + MAX = 2 ** 7 - 1 + MIN = - (2 ** 7) + + def test_int8_return(self): + self.assertEquals(self.MAX, TestGI.int8_return_max()) + self.assertEquals(self.MIN, TestGI.int8_return_min()) + + def test_int8_return_ptr(self): + self.assertEquals(self.MAX, TestGI.int8_return_ptr_max()) + self.assertEquals(self.MIN, TestGI.int8_return_ptr_min()) + + def test_int8_in(self): + max = Number(self.MAX) + min = Number(self.MIN) + + TestGI.int8_in_max(max) + TestGI.int8_in_min(min) + + max.value += 1 + min.value -= 1 + + self.assertRaises(ValueError, TestGI.int8_in_max, max) + self.assertRaises(ValueError, TestGI.int8_in_min, min) + + self.assertRaises(TypeError, TestGI.int8_in_max, "self.MAX") + + def test_int8_in_ptr(self): + TestGI.int8_in_ptr_max(Number(self.MAX)) + TestGI.int8_in_ptr_min(Number(self.MIN)) + self.assertRaises(TypeError, TestGI.int8_in_ptr_max, None) + + def test_int8_out(self): + self.assertEquals(self.MAX, TestGI.int8_out_max()) + self.assertEquals(self.MIN, TestGI.int8_out_min()) + + def test_int8_inout(self): + self.assertEquals(self.MIN, TestGI.int8_inout_max_min(Number(self.MAX))) + self.assertEquals(self.MAX, TestGI.int8_inout_min_max(Number(self.MIN))) + + +class TestUInt8(unittest.TestCase): + + MAX = 2 ** 8 - 1 + + def test_uint8_return(self): + self.assertEquals(self.MAX, TestGI.uint8_return()) + +# Blocked by https://bugzilla.gnome.org/show_bug.cgi?id=596420 +# def test_uint8_return_ptr(self): +# self.assertEquals(self.MAX, TestGI.uint8_return_ptr()) + + def test_uint8_in(self): + number = Number(self.MAX) + + TestGI.uint8_in(number) + + number.value += 1 + + self.assertRaises(ValueError, TestGI.uint8_in, number) + self.assertRaises(ValueError, TestGI.uint8_in, Number(-1)) + + self.assertRaises(TypeError, TestGI.uint8_in, "self.MAX") + + def test_uint8_out(self): + self.assertEquals(self.MAX, TestGI.uint8_out()) + + def test_uint8_inout(self): + self.assertEquals(0, TestGI.uint8_inout(Number(self.MAX))) + + +class TestInt16(unittest.TestCase): + + MAX = 2 ** 15 - 1 + MIN = - (2 ** 15) + + def test_int16_return(self): + self.assertEquals(self.MAX, TestGI.int16_return_max()) + self.assertEquals(self.MIN, TestGI.int16_return_min()) + + def test_int16_return_ptr(self): + self.assertEquals(self.MAX, TestGI.int16_return_ptr_max()) + self.assertEquals(self.MIN, TestGI.int16_return_ptr_min()) + + def test_int16_in(self): + max = Number(self.MAX) + min = Number(self.MIN) + + TestGI.int16_in_max(max) + TestGI.int16_in_min(min) + + max.value += 1 + min.value -= 1 + + self.assertRaises(ValueError, TestGI.int16_in_max, max) + self.assertRaises(ValueError, TestGI.int16_in_min, min) + + self.assertRaises(TypeError, TestGI.int16_in_max, "self.MAX") + + def test_int16_in_ptr(self): + TestGI.int16_in_ptr_max(Number(self.MAX)) + TestGI.int16_in_ptr_min(Number(self.MIN)) + self.assertRaises(TypeError, TestGI.int16_in_ptr_max, None) + + def test_int16_out(self): + self.assertEquals(self.MAX, TestGI.int16_out_max()) + self.assertEquals(self.MIN, TestGI.int16_out_min()) + + def test_int16_inout(self): + self.assertEquals(self.MIN, TestGI.int16_inout_max_min(Number(self.MAX))) + self.assertEquals(self.MAX, TestGI.int16_inout_min_max(Number(self.MIN))) + + +class TestUInt16(unittest.TestCase): + + MAX = 2 ** 16 - 1 + + def test_uint16_return(self): + self.assertEquals(self.MAX, TestGI.uint16_return()) + + def test_uint16_return_ptr(self): + self.assertEquals(self.MAX, TestGI.uint16_return_ptr()) + + def test_uint16_in(self): + number = Number(self.MAX) + + TestGI.uint16_in(number) + + number.value += 1 + + self.assertRaises(ValueError, TestGI.uint16_in, number) + self.assertRaises(ValueError, TestGI.uint16_in, Number(-1)) + + self.assertRaises(TypeError, TestGI.uint16_in, "self.MAX") + + def test_uint16_out(self): + self.assertEquals(self.MAX, TestGI.uint16_out()) + + def test_uint16_inout(self): + self.assertEquals(0, TestGI.uint16_inout(Number(self.MAX))) + + +class TestInt32(unittest.TestCase): + + MAX = 2 ** 31 - 1 + MIN = - (2 ** 31) + + def test_int32_return(self): + self.assertEquals(self.MAX, TestGI.int32_return_max()) + self.assertEquals(self.MIN, TestGI.int32_return_min()) + + def test_int32_return_ptr(self): + self.assertEquals(self.MAX, TestGI.int32_return_ptr_max()) + self.assertEquals(self.MIN, TestGI.int32_return_ptr_min()) + + def test_int32_in(self): + max = Number(self.MAX) + min = Number(self.MIN) + + TestGI.int32_in_max(max) + TestGI.int32_in_min(min) + + max.value += 1 + min.value -= 1 + + self.assertRaises(ValueError, TestGI.int32_in_max, max) + self.assertRaises(ValueError, TestGI.int32_in_min, min) + + self.assertRaises(TypeError, TestGI.int32_in_max, "self.MAX") + + def test_int32_in_ptr(self): + TestGI.int32_in_ptr_max(Number(self.MAX)) + TestGI.int32_in_ptr_min(Number(self.MIN)) + self.assertRaises(TypeError, TestGI.int32_in_ptr_max, None) + + def test_int32_out(self): + self.assertEquals(self.MAX, TestGI.int32_out_max()) + self.assertEquals(self.MIN, TestGI.int32_out_min()) + + def test_int32_inout(self): + self.assertEquals(self.MIN, TestGI.int32_inout_max_min(Number(self.MAX))) + self.assertEquals(self.MAX, TestGI.int32_inout_min_max(Number(self.MIN))) + + +class TestUInt32(unittest.TestCase): + + MAX = 2 ** 32 - 1 + + def test_uint32_return(self): + self.assertEquals(self.MAX, TestGI.uint32_return()) + + def test_uint32_return_ptr(self): + self.assertEquals(self.MAX, TestGI.uint32_return_ptr()) + + def test_uint32_in(self): + number = Number(self.MAX) + + TestGI.uint32_in(number) + + number.value += 1 + + self.assertRaises(ValueError, TestGI.uint32_in, number) + self.assertRaises(ValueError, TestGI.uint32_in, Number(-1)) + + self.assertRaises(TypeError, TestGI.uint32_in, "self.MAX") + + def test_uint32_out(self): + self.assertEquals(self.MAX, TestGI.uint32_out()) + + def test_uint32_inout(self): + self.assertEquals(0, TestGI.uint32_inout(Number(self.MAX))) + + +class TestInt64(unittest.TestCase): + + MAX = 2 ** 63 - 1 + MIN = - (2 ** 63) + + def test_int64_return(self): + self.assertEquals(self.MAX, TestGI.int64_return_max()) + self.assertEquals(self.MIN, TestGI.int64_return_min()) + + def test_int64_return_ptr(self): + self.assertEquals(self.MAX, TestGI.int64_return_ptr_max()) + self.assertEquals(self.MIN, TestGI.int64_return_ptr_min()) + + def test_int64_in(self): + max = Number(self.MAX) + min = Number(self.MIN) + + TestGI.int64_in_max(max) + TestGI.int64_in_min(min) + + max.value += 1 + min.value -= 1 + + self.assertRaises(ValueError, TestGI.int64_in_max, max) + self.assertRaises(ValueError, TestGI.int64_in_min, min) + + self.assertRaises(TypeError, TestGI.int64_in_max, "self.MAX") + + def test_int64_in_ptr(self): + TestGI.int64_in_ptr_max(Number(self.MAX)) + TestGI.int64_in_ptr_min(Number(self.MIN)) + self.assertRaises(TypeError, TestGI.int64_in_ptr_max, None) + + def test_int64_out(self): + self.assertEquals(self.MAX, TestGI.int64_out_max()) + self.assertEquals(self.MIN, TestGI.int64_out_min()) + + def test_int64_inout(self): + self.assertEquals(self.MIN, TestGI.int64_inout_max_min(Number(self.MAX))) + self.assertEquals(self.MAX, TestGI.int64_inout_min_max(Number(self.MIN))) + + +class TestUInt64(unittest.TestCase): + + MAX = 2 ** 64 - 1 + + def test_uint64_return(self): + self.assertEquals(self.MAX, TestGI.uint64_return()) + + def test_uint64_return_ptr(self): + self.assertEquals(self.MAX, TestGI.uint64_return_ptr()) + + def test_uint64_in(self): + number = Number(self.MAX) + + TestGI.uint64_in(number) + + number.value += 1 + + self.assertRaises(ValueError, TestGI.uint64_in, number) + self.assertRaises(ValueError, TestGI.uint64_in, Number(-1)) + + self.assertRaises(TypeError, TestGI.uint64_in, "self.MAX") + + def test_uint64_out(self): + self.assertEquals(self.MAX, TestGI.uint64_out()) + + def test_uint64_inout(self): + self.assertEquals(0, TestGI.uint64_inout(Number(self.MAX))) + + +class TestShort(unittest.TestCase): + + MAX = gobject.constants.G_MAXSHORT + MIN = gobject.constants.G_MINSHORT + + def test_short_return(self): + self.assertEquals(self.MAX, TestGI.short_return_max()) + self.assertEquals(self.MIN, TestGI.short_return_min()) + + def test_short_return_ptr(self): + self.assertEquals(self.MAX, TestGI.short_return_ptr_max()) + self.assertEquals(self.MIN, TestGI.short_return_ptr_min()) + + def test_short_in(self): + max = Number(self.MAX) + min = Number(self.MIN) + + TestGI.short_in_max(max) + TestGI.short_in_min(min) + + max.value += 1 + min.value -= 1 + + self.assertRaises(ValueError, TestGI.short_in_max, max) + self.assertRaises(ValueError, TestGI.short_in_min, min) + + self.assertRaises(TypeError, TestGI.short_in_max, "self.MAX") + + def test_short_in_ptr(self): + TestGI.short_in_ptr_max(Number(self.MAX)) + TestGI.short_in_ptr_min(Number(self.MIN)) + self.assertRaises(TypeError, TestGI.short_in_ptr_max, None) + + def test_short_out(self): + self.assertEquals(self.MAX, TestGI.short_out_max()) + self.assertEquals(self.MIN, TestGI.short_out_min()) + + def test_short_inout(self): + self.assertEquals(self.MIN, TestGI.short_inout_max_min(Number(self.MAX))) + self.assertEquals(self.MAX, TestGI.short_inout_min_max(Number(self.MIN))) + + +class TestUShort(unittest.TestCase): + + MAX = gobject.constants.G_MAXUSHORT + + def test_ushort_return(self): + self.assertEquals(self.MAX, TestGI.ushort_return()) + + def test_ushort_return_ptr(self): + self.assertEquals(self.MAX, TestGI.ushort_return_ptr()) + + def test_ushort_in(self): + number = Number(self.MAX) + + TestGI.ushort_in(number) + + number.value += 1 + + self.assertRaises(ValueError, TestGI.ushort_in, number) + self.assertRaises(ValueError, TestGI.ushort_in, Number(-1)) + + self.assertRaises(TypeError, TestGI.ushort_in, "self.MAX") + + def test_ushort_out(self): + self.assertEquals(self.MAX, TestGI.ushort_out()) + + def test_ushort_inout(self): + self.assertEquals(0, TestGI.ushort_inout(Number(self.MAX))) + + +class TestInt(unittest.TestCase): + + MAX = gobject.constants.G_MAXINT + MIN = gobject.constants.G_MININT + + def test_int_return(self): + self.assertEquals(self.MAX, TestGI.int_return_max()) + self.assertEquals(self.MIN, TestGI.int_return_min()) + + def test_int_return_ptr(self): + self.assertEquals(self.MAX, TestGI.int_return_ptr_max()) + self.assertEquals(self.MIN, TestGI.int_return_ptr_min()) + + def test_int_in(self): + max = Number(self.MAX) + min = Number(self.MIN) + + TestGI.int_in_max(max) + TestGI.int_in_min(min) + + max.value += 1 + min.value -= 1 + + self.assertRaises(ValueError, TestGI.int_in_max, max) + self.assertRaises(ValueError, TestGI.int_in_min, min) + + self.assertRaises(TypeError, TestGI.int_in_max, "self.MAX") + + def test_int_in_ptr(self): + TestGI.int_in_ptr_max(Number(self.MAX)) + TestGI.int_in_ptr_min(Number(self.MIN)) + self.assertRaises(TypeError, TestGI.int_in_ptr_max, None) + + def test_int_out(self): + self.assertEquals(self.MAX, TestGI.int_out_max()) + self.assertEquals(self.MIN, TestGI.int_out_min()) + + def test_int_inout(self): + self.assertEquals(self.MIN, TestGI.int_inout_max_min(Number(self.MAX))) + self.assertEquals(self.MAX, TestGI.int_inout_min_max(Number(self.MIN))) + + +class TestUInt(unittest.TestCase): + + MAX = gobject.constants.G_MAXUINT + + def test_uint_return(self): + self.assertEquals(self.MAX, TestGI.uint_return()) + + def test_uint_return_ptr(self): + self.assertEquals(self.MAX, TestGI.uint_return_ptr()) + + def test_uint_in(self): + number = Number(self.MAX) + + TestGI.uint_in(number) + + number.value += 1 + + self.assertRaises(ValueError, TestGI.uint_in, number) + self.assertRaises(ValueError, TestGI.uint_in, Number(-1)) + + self.assertRaises(TypeError, TestGI.uint_in, "self.MAX") + + def test_uint_out(self): + self.assertEquals(self.MAX, TestGI.uint_out()) + + def test_uint_inout(self): + self.assertEquals(0, TestGI.uint_inout(Number(self.MAX))) + + +class TestLong(unittest.TestCase): + + MAX = gobject.constants.G_MAXLONG + MIN = gobject.constants.G_MINLONG + + def test_long_return(self): + self.assertEquals(self.MAX, TestGI.long_return_max()) + self.assertEquals(self.MIN, TestGI.long_return_min()) + + def test_long_return_ptr(self): + self.assertEquals(self.MAX, TestGI.long_return_ptr_max()) + self.assertEquals(self.MIN, TestGI.long_return_ptr_min()) + + def test_long_in(self): + max = Number(self.MAX) + min = Number(self.MIN) + + TestGI.long_in_max(max) + TestGI.long_in_min(min) + + max.value += 1 + min.value -= 1 + + self.assertRaises(ValueError, TestGI.long_in_max, max) + self.assertRaises(ValueError, TestGI.long_in_min, min) + + self.assertRaises(TypeError, TestGI.long_in_max, "self.MAX") + + def test_long_in_ptr(self): + TestGI.long_in_ptr_max(Number(self.MAX)) + TestGI.long_in_ptr_min(Number(self.MIN)) + self.assertRaises(TypeError, TestGI.long_in_ptr_max, None) + + def test_long_out(self): + self.assertEquals(self.MAX, TestGI.long_out_max()) + self.assertEquals(self.MIN, TestGI.long_out_min()) + + def test_long_inout(self): + self.assertEquals(self.MIN, TestGI.long_inout_max_min(Number(self.MAX))) + self.assertEquals(self.MAX, TestGI.long_inout_min_max(Number(self.MIN))) + + +class TestULong(unittest.TestCase): + + MAX = gobject.constants.G_MAXULONG + + def test_ulong_return(self): + self.assertEquals(self.MAX, TestGI.ulong_return()) + + def test_ulong_return_ptr(self): + self.assertEquals(self.MAX, TestGI.ulong_return_ptr()) + + def test_ulong_in(self): + number = Number(self.MAX) + + TestGI.ulong_in(number) + + number.value += 1 + + self.assertRaises(ValueError, TestGI.ulong_in, number) + self.assertRaises(ValueError, TestGI.ulong_in, Number(-1)) + + self.assertRaises(TypeError, TestGI.ulong_in, "self.MAX") + + def test_ulong_out(self): + self.assertEquals(self.MAX, TestGI.ulong_out()) + + def test_ulong_inout(self): + self.assertEquals(0, TestGI.ulong_inout(Number(self.MAX))) + + +class TestSSize(unittest.TestCase): + + MAX = gobject.constants.G_MAXLONG + MIN = gobject.constants.G_MINLONG + + def test_ssize_return(self): + self.assertEquals(self.MAX, TestGI.ssize_return_max()) + self.assertEquals(self.MIN, TestGI.ssize_return_min()) + + def test_ssize_return_ptr(self): + self.assertEquals(self.MAX, TestGI.ssize_return_ptr_max()) + self.assertEquals(self.MIN, TestGI.ssize_return_ptr_min()) + + def test_ssize_in(self): + max = Number(self.MAX) + min = Number(self.MIN) + + TestGI.ssize_in_max(max) + TestGI.ssize_in_min(min) + + max.value += 1 + min.value -= 1 + + self.assertRaises(ValueError, TestGI.ssize_in_max, max) + self.assertRaises(ValueError, TestGI.ssize_in_min, min) + + self.assertRaises(TypeError, TestGI.ssize_in_max, "self.MAX") + + def test_ssize_in_ptr(self): + TestGI.ssize_in_ptr_max(Number(self.MAX)) + TestGI.ssize_in_ptr_min(Number(self.MIN)) + self.assertRaises(TypeError, TestGI.ssize_in_ptr_max, None) + + def test_ssize_out(self): + self.assertEquals(self.MAX, TestGI.ssize_out_max()) + self.assertEquals(self.MIN, TestGI.ssize_out_min()) + + def test_ssize_inout(self): + self.assertEquals(self.MIN, TestGI.ssize_inout_max_min(Number(self.MAX))) + self.assertEquals(self.MAX, TestGI.ssize_inout_min_max(Number(self.MIN))) + + +class TestSize(unittest.TestCase): + + MAX = gobject.constants.G_MAXULONG + + def test_size_return(self): + self.assertEquals(self.MAX, TestGI.size_return()) + + def test_size_return_ptr(self): + self.assertEquals(self.MAX, TestGI.size_return_ptr()) + + def test_size_in(self): + number = Number(self.MAX) + + TestGI.size_in(number) + + number.value += 1 + + self.assertRaises(ValueError, TestGI.size_in, number) + self.assertRaises(ValueError, TestGI.size_in, Number(-1)) + + self.assertRaises(TypeError, TestGI.size_in, "self.MAX") + + def test_size_out(self): + self.assertEquals(self.MAX, TestGI.size_out()) + + def test_size_inout(self): + self.assertEquals(0, TestGI.size_inout(Number(self.MAX))) + + +class TestFloat(unittest.TestCase): + + MAX = gobject.constants.G_MAXFLOAT + MIN = gobject.constants.G_MINFLOAT + + def test_float_return(self): + self.assertAlmostEquals(self.MAX, TestGI.float_return()) + + def test_float_return_ptr(self): + self.assertAlmostEquals(self.MAX, TestGI.float_return_ptr()) + + def test_float_in(self): + TestGI.float_in(Number(self.MAX)) + + self.assertRaises(TypeError, TestGI.float_in, "self.MAX") + + def test_float_in_ptr(self): + TestGI.float_in_ptr(Number(self.MAX)) + self.assertRaises(TypeError, TestGI.float_in_ptr, None) + + def test_float_out(self): + self.assertAlmostEquals(self.MAX, TestGI.float_out()) + + def test_float_inout(self): + self.assertAlmostEquals(self.MIN, TestGI.float_inout(Number(self.MAX))) + + +class TestDouble(unittest.TestCase): + + MAX = gobject.constants.G_MAXDOUBLE + MIN = gobject.constants.G_MINDOUBLE + + def test_double_return(self): + self.assertAlmostEquals(self.MAX, TestGI.double_return()) + + def test_double_return_ptr(self): + self.assertAlmostEquals(self.MAX, TestGI.double_return_ptr()) + + def test_double_in(self): + TestGI.double_in(Number(self.MAX)) + + self.assertRaises(TypeError, TestGI.double_in, "self.MAX") + + def test_double_in_ptr(self): + TestGI.double_in_ptr(Number(self.MAX)) + self.assertRaises(TypeError, TestGI.double_in_ptr, None) + + def test_double_out(self): + self.assertAlmostEquals(self.MAX, TestGI.double_out()) + + def test_double_inout(self): + self.assertAlmostEquals(self.MIN, TestGI.double_inout(Number(self.MAX))) + + +class TestTimeT(unittest.TestCase): + + DATETIME = datetime.fromtimestamp(1234567890) + + def test_time_t_return(self): + self.assertEquals(self.DATETIME, TestGI.time_t_return()) + + def test_time_t_return_ptr(self): + self.assertEquals(self.DATETIME, TestGI.time_t_return_ptr()) + + def test_time_t_in(self): + TestGI.time_t_in(self.DATETIME) + + self.assertRaises(TypeError, TestGI.time_t_in, "self.DATETIME") + + def test_time_t_in_ptr(self): + TestGI.time_t_in_ptr(self.DATETIME) + self.assertRaises(TypeError, TestGI.time_t_in_ptr, None) + + def test_time_t_out(self): + self.assertEquals(self.DATETIME, TestGI.time_t_out()) + + def test_time_t_inout(self): + self.assertEquals(datetime.fromtimestamp(0), TestGI.time_t_inout(self.DATETIME)) + + +class TestGType(unittest.TestCase): + + def test_gtype_return(self): + self.assertEquals(gobject.TYPE_NONE, TestGI.gtype_return()) + + def test_gtype_return_ptr(self): + self.assertEquals(gobject.TYPE_NONE, TestGI.gtype_return_ptr()) + + def test_gtype_in(self): + TestGI.gtype_in(gobject.TYPE_NONE) + + self.assertRaises(TypeError, TestGI.gtype_in, "gobject.TYPE_NONE") + + def test_gtype_in_ptr(self): + TestGI.gtype_in_ptr(gobject.TYPE_NONE) + self.assertRaises(TypeError, TestGI.gtype_in_ptr, None) + + def test_gtype_out(self): + self.assertEquals(gobject.TYPE_NONE, TestGI.gtype_out()) + + def test_gtype_inout(self): + self.assertEquals(gobject.TYPE_INT, TestGI.gtype_inout(gobject.TYPE_NONE)) + + +class TestUtf8(unittest.TestCase): + + def test_utf8_none_return(self): + self.assertEquals(CONSTANT_UTF8, TestGI.utf8_none_return()) + + def test_utf8_full_return(self): + self.assertEquals(CONSTANT_UTF8, TestGI.utf8_full_return()) + + def test_utf8_none_in(self): + TestGI.utf8_none_in(CONSTANT_UTF8) + + self.assertRaises(TypeError, TestGI.utf8_none_in, CONSTANT_NUMBER) + self.assertRaises(TypeError, TestGI.utf8_none_in, None) + + def test_utf8_full_in(self): + TestGI.utf8_full_in(CONSTANT_UTF8) + + def test_utf8_none_out(self): + self.assertEquals(CONSTANT_UTF8, TestGI.utf8_none_out()) + + def test_utf8_full_out(self): + self.assertEquals(CONSTANT_UTF8, TestGI.utf8_full_out()) + + def test_utf8_none_inout(self): + self.assertEquals("", TestGI.utf8_none_inout(CONSTANT_UTF8)) + + def test_utf8_full_inout(self): + self.assertEquals("", TestGI.utf8_full_inout(CONSTANT_UTF8)) + + +class TestArray(unittest.TestCase): + + def test_array_fixed_int_return(self): + self.assertEquals((-1, 0, 1, 2), TestGI.array_fixed_int_return()) + + def test_array_fixed_short_return(self): + self.assertEquals((-1, 0, 1, 2), TestGI.array_fixed_short_return()) + + def test_array_fixed_int_in(self): + TestGI.array_fixed_int_in(Sequence((-1, 0, 1, 2))) + + self.assertRaises(TypeError, TestGI.array_fixed_int_in, Sequence((-1, '0', 1, 2))) + + self.assertRaises(TypeError, TestGI.array_fixed_int_in, 42) + self.assertRaises(TypeError, TestGI.array_fixed_int_in, None) + + def test_array_fixed_short_in(self): + TestGI.array_fixed_short_in(Sequence((-1, 0, 1, 2))) + + def test_array_fixed_out(self): + self.assertEquals((-1, 0, 1, 2), TestGI.array_fixed_out()) + + def test_array_fixed_inout(self): + self.assertEquals((2, 1, 0, -1), TestGI.array_fixed_inout((-1, 0, 1, 2))) + + + def test_array_return(self): + self.assertEquals((-1, 0, 1, 2), TestGI.array_return()) + + def test_array_in(self): + TestGI.array_in(Sequence((-1, 0, 1, 2))) + + def test_array_out(self): + self.assertEquals((-1, 0, 1, 2), TestGI.array_out()) + + def test_array_inout(self): + self.assertEquals((-2, -1, 0, 1, 2), TestGI.array_inout(Sequence((-1, 0, 1, 2)))) + + + def test_array_zero_terminated_return(self): + self.assertEquals(('0', '1', '2'), TestGI.array_zero_terminated_return()) + + def test_array_zero_terminated_in(self): + TestGI.array_zero_terminated_in(Sequence(('0', '1', '2'))) + + def test_array_zero_terminated_out(self): + self.assertEquals(('0', '1', '2'), TestGI.array_zero_terminated_out()) + + def test_array_zero_terminated_out(self): + self.assertEquals(('0', '1', '2'), TestGI.array_zero_terminated_out()) + + def test_array_zero_terminated_inout(self): + self.assertEquals(('-1', '0', '1', '2'), TestGI.array_zero_terminated_inout(('0', '1', '2'))) + + +class TestGList(unittest.TestCase): + + def test_glist_int_none_return(self): + self.assertEquals([-1, 0, 1, 2], TestGI.glist_int_none_return()) + + def test_glist_utf8_none_return(self): + self.assertEquals(['0', '1', '2'], TestGI.glist_utf8_none_return()) + + def test_glist_utf8_container_return(self): + self.assertEquals(['0', '1', '2'], TestGI.glist_utf8_container_return()) + + def test_glist_utf8_full_return(self): + self.assertEquals(['0', '1', '2'], TestGI.glist_utf8_full_return()) + + def test_glist_int_none_in(self): + TestGI.glist_int_none_in(Sequence((-1, 0, 1, 2))) + + self.assertRaises(TypeError, TestGI.glist_int_none_in, Sequence((-1, '0', 1, 2))) + + self.assertRaises(TypeError, TestGI.glist_int_none_in, 42) + self.assertRaises(TypeError, TestGI.glist_int_none_in, None) + + def test_glist_utf8_none_in(self): + TestGI.glist_utf8_none_in(Sequence(('0', '1', '2'))) + + def test_glist_utf8_container_in(self): + TestGI.glist_utf8_container_in(Sequence(('0', '1', '2'))) + + def test_glist_utf8_full_in(self): + TestGI.glist_utf8_full_in(Sequence(('0', '1', '2'))) + + def test_glist_utf8_none_out(self): + self.assertEquals(['0', '1', '2'], TestGI.glist_utf8_none_out()) + + def test_glist_utf8_container_out(self): + self.assertEquals(['0', '1', '2'], TestGI.glist_utf8_container_out()) + + def test_glist_utf8_full_out(self): + self.assertEquals(['0', '1', '2'], TestGI.glist_utf8_full_out()) + + def test_glist_utf8_none_inout(self): + self.assertEquals(['-2', '-1', '0', '1'], TestGI.glist_utf8_none_inout(Sequence(('0', '1', '2')))) + + def test_glist_utf8_container_inout(self): + self.assertEquals(['-2', '-1','0', '1'], TestGI.glist_utf8_container_inout(('0', '1', '2'))) + + def test_glist_utf8_full_inout(self): + self.assertEquals(['-2', '-1','0', '1'], TestGI.glist_utf8_full_inout(('0', '1', '2'))) + + +class TestGSList(unittest.TestCase): + + def test_gslist_int_none_return(self): + self.assertEquals([-1, 0, 1, 2], TestGI.gslist_int_none_return()) + + def test_gslist_utf8_none_return(self): + self.assertEquals(['0', '1', '2'], TestGI.gslist_utf8_none_return()) + + def test_gslist_utf8_container_return(self): + self.assertEquals(['0', '1', '2'], TestGI.gslist_utf8_container_return()) + + def test_gslist_utf8_full_return(self): + self.assertEquals(['0', '1', '2'], TestGI.gslist_utf8_full_return()) + + def test_gslist_int_none_in(self): + TestGI.gslist_int_none_in(Sequence((-1, 0, 1, 2))) + + self.assertRaises(TypeError, TestGI.gslist_int_none_in, Sequence((-1, '0', 1, 2))) + + self.assertRaises(TypeError, TestGI.gslist_int_none_in, 42) + self.assertRaises(TypeError, TestGI.gslist_int_none_in, None) + + def test_gslist_utf8_none_in(self): + TestGI.gslist_utf8_none_in(Sequence(('0', '1', '2'))) + + def test_gslist_utf8_container_in(self): + TestGI.gslist_utf8_container_in(Sequence(('0', '1', '2'))) + + def test_gslist_utf8_full_in(self): + TestGI.gslist_utf8_full_in(Sequence(('0', '1', '2'))) + + def test_gslist_utf8_none_out(self): + self.assertEquals(['0', '1', '2'], TestGI.gslist_utf8_none_out()) + + def test_gslist_utf8_container_out(self): + self.assertEquals(['0', '1', '2'], TestGI.gslist_utf8_container_out()) + + def test_gslist_utf8_full_out(self): + self.assertEquals(['0', '1', '2'], TestGI.gslist_utf8_full_out()) + + def test_gslist_utf8_none_inout(self): + self.assertEquals(['-2', '-1', '0', '1'], TestGI.gslist_utf8_none_inout(Sequence(('0', '1', '2')))) + + def test_gslist_utf8_container_inout(self): + self.assertEquals(['-2', '-1','0', '1'], TestGI.gslist_utf8_container_inout(('0', '1', '2'))) + + def test_gslist_utf8_full_inout(self): + self.assertEquals(['-2', '-1','0', '1'], TestGI.gslist_utf8_full_inout(('0', '1', '2'))) + + +class TestGHashTable(unittest.TestCase): + + def test_ghashtable_int_none_return(self): + self.assertEquals({-1: 1, 0: 0, 1: -1, 2: -2}, TestGI.ghashtable_int_none_return()) + + def test_ghashtable_int_none_return(self): + self.assertEquals({'-1': '1', '0': '0', '1': '-1', '2': '-2'}, TestGI.ghashtable_utf8_none_return()) + + def test_ghashtable_int_container_return(self): + self.assertEquals({'-1': '1', '0': '0', '1': '-1', '2': '-2'}, TestGI.ghashtable_utf8_container_return()) + + def test_ghashtable_int_full_return(self): + self.assertEquals({'-1': '1', '0': '0', '1': '-1', '2': '-2'}, TestGI.ghashtable_utf8_full_return()) + + def test_ghashtable_int_none_in(self): + TestGI.ghashtable_int_none_in({-1: 1, 0: 0, 1: -1, 2: -2}) + + self.assertRaises(TypeError, TestGI.ghashtable_int_none_in, {-1: 1, '0': 0, 1: -1, 2: -2}) + self.assertRaises(TypeError, TestGI.ghashtable_int_none_in, {-1: 1, 0: '0', 1: -1, 2: -2}) + + self.assertRaises(TypeError, TestGI.ghashtable_int_none_in, '{-1: 1, 0: 0, 1: -1, 2: -2}') + self.assertRaises(TypeError, TestGI.ghashtable_int_none_in, None) + + def test_ghashtable_utf8_none_in(self): + TestGI.ghashtable_utf8_none_in({'-1': '1', '0': '0', '1': '-1', '2': '-2'}) + + def test_ghashtable_utf8_container_in(self): + TestGI.ghashtable_utf8_container_in({'-1': '1', '0': '0', '1': '-1', '2': '-2'}) + + def test_ghashtable_utf8_full_in(self): + TestGI.ghashtable_utf8_full_in({'-1': '1', '0': '0', '1': '-1', '2': '-2'}) + + def test_ghashtable_utf8_none_out(self): + self.assertEquals({'-1': '1', '0': '0', '1': '-1', '2': '-2'}, TestGI.ghashtable_utf8_none_out()) + + def test_ghashtable_utf8_container_out(self): + self.assertEquals({'-1': '1', '0': '0', '1': '-1', '2': '-2'}, TestGI.ghashtable_utf8_container_out()) + + def test_ghashtable_utf8_full_out(self): + self.assertEquals({'-1': '1', '0': '0', '1': '-1', '2': '-2'}, TestGI.ghashtable_utf8_full_out()) + + def test_ghashtable_utf8_none_inout(self): + self.assertEquals({'-1': '1', '0': '0', '1': '1'}, + TestGI.ghashtable_utf8_none_inout({'-1': '1', '0': '0', '1': '-1', '2': '-2'})) + + def test_ghashtable_utf8_container_inout(self): + self.assertEquals({'-1': '1', '0': '0', '1': '1'}, + TestGI.ghashtable_utf8_container_inout({'-1': '1', '0': '0', '1': '-1', '2': '-2'})) + + def test_ghashtable_utf8_full_inout(self): + self.assertEquals({'-1': '1', '0': '0', '1': '1'}, + TestGI.ghashtable_utf8_full_inout({'-1': '1', '0': '0', '1': '-1', '2': '-2'})) + + +class TestGValue(unittest.TestCase): + + def test_gvalue_return(self): + self.assertEquals(42, TestGI.gvalue_return()) + + def test_gvalue_in(self): + TestGI.gvalue_in(42) + self.assertRaises(TypeError, TestGI.gvalue_in, None) + + def test_gvalue_out(self): + self.assertEquals(42, TestGI.gvalue_out()) + + def test_gvalue_inout(self): + self.assertEquals('42', TestGI.gvalue_inout(42)) + + +class TestGClosure(unittest.TestCase): + + def test_gclosure_in(self): + TestGI.gclosure_in(lambda: 42) + + self.assertRaises(TypeError, TestGI.gclosure_in, 42) + self.assertRaises(TypeError, TestGI.gclosure_in, None) + + +class TestGEnum(unittest.TestCase): + + def test_enum(self): + self.assertTrue(issubclass(TestGI.Enum, gobject.GEnum)) + self.assertTrue(isinstance(TestGI.Enum.VALUE1, TestGI.Enum)) + self.assertTrue(isinstance(TestGI.Enum.VALUE2, TestGI.Enum)) + self.assertTrue(isinstance(TestGI.Enum.VALUE3, TestGI.Enum)) + self.assertEquals(42, TestGI.Enum.VALUE3) + + def test_enum_in(self): + TestGI.enum_in(TestGI.Enum.VALUE3) + + self.assertRaises(TypeError, TestGI.enum_in, 42) + self.assertRaises(TypeError, TestGI.enum_in, 'TestGI.Enum.VALUE3') + + def test_enum_in_ptr(self): + TestGI.enum_in_ptr(TestGI.Enum.VALUE3) + + self.assertRaises(TypeError, TestGI.enum_in_ptr, None) + + def test_enum_out(self): + enum = TestGI.enum_out() + self.assertTrue(isinstance(enum, TestGI.Enum)) + self.assertEquals(enum, TestGI.Enum.VALUE3) + + def test_enum_inout(self): + enum = TestGI.enum_inout(TestGI.Enum.VALUE3) + self.assertTrue(isinstance(enum, TestGI.Enum)) + self.assertEquals(enum, TestGI.Enum.VALUE1) + + +class TestGFlags(unittest.TestCase): + + def test_flags(self): + self.assertTrue(issubclass(TestGI.Flags, gobject.GFlags)) + self.assertTrue(isinstance(TestGI.Flags.VALUE1, TestGI.Flags)) + self.assertTrue(isinstance(TestGI.Flags.VALUE2, TestGI.Flags)) + self.assertTrue(isinstance(TestGI.Flags.VALUE3, TestGI.Flags)) + self.assertEquals(1 << 1, TestGI.Flags.VALUE2) + + def test_flags_in(self): + TestGI.flags_in(TestGI.Flags.VALUE2) + + self.assertRaises(TypeError, TestGI.flags_in, 1 << 1) + self.assertRaises(TypeError, TestGI.flags_in, 'TestGI.Flags.VALUE2') + + def test_flags_in_ptr(self): + TestGI.flags_in_ptr(TestGI.Flags.VALUE2) + + self.assertRaises(TypeError, TestGI.flags_in_ptr, None) + + def test_flags_out(self): + flags = TestGI.flags_out() + self.assertTrue(isinstance(flags, TestGI.Flags)) + self.assertEquals(flags, TestGI.Flags.VALUE2) + + def test_flags_inout(self): + flags = TestGI.flags_inout(TestGI.Flags.VALUE2) + self.assertTrue(isinstance(flags, TestGI.Flags)) + self.assertEquals(flags, TestGI.Flags.VALUE1) + + +class TestStructure(unittest.TestCase): + + def test_simple_struct(self): + self.assertTrue(issubclass(TestGI.SimpleStruct, gobject.GPointer)) + + struct = TestGI.SimpleStruct() + self.assertTrue(isinstance(struct, TestGI.SimpleStruct)) + + struct.long_ = 6 + struct.int8 = 7 + + self.assertEquals(6, struct.long_) + self.assertEquals(7, struct.int8) + + del struct + + def test_nested_struct(self): + struct = TestGI.NestedStruct() + + self.assertTrue(isinstance(struct.simple_struct, TestGI.SimpleStruct)) + + struct.simple_struct.long_ = 42 + self.assertEquals(42, struct.simple_struct.long_) + + del struct + + def test_not_simple_struct(self): + self.assertRaises(TypeError, TestGI.NotSimpleStruct) + + def test_simple_struct_return(self): + struct = TestGI.simple_struct_return() + + self.assertTrue(isinstance(struct, TestGI.SimpleStruct)) + self.assertEquals(6, struct.long_) + self.assertEquals(7, struct.int8) + + del struct + + def test_simple_struct_in(self): + struct = TestGI.SimpleStruct() + struct.long_ = 6 + struct.int8 = 7 + + TestGI.simple_struct_in(struct) + + del struct + + struct = TestGI.NestedStruct() + + self.assertRaises(TypeError, TestGI.simple_struct_in, struct) + + del struct + + self.assertRaises(TypeError, TestGI.simple_struct_in, None) + + def test_simple_struct_out(self): + struct = TestGI.simple_struct_out() + + self.assertTrue(isinstance(struct, TestGI.SimpleStruct)) + self.assertEquals(6, struct.long_) + self.assertEquals(7, struct.int8) + + del struct + + def test_simple_struct_inout(self): + in_struct = TestGI.SimpleStruct() + in_struct.long_ = 6 + in_struct.int8 = 7 + + out_struct = TestGI.simple_struct_inout(in_struct) + + self.assertTrue(isinstance(out_struct, TestGI.SimpleStruct)) + self.assertEquals(7, out_struct.long_) + self.assertEquals(6, out_struct.int8) + + del in_struct + del out_struct + + def test_simple_struct_method(self): + struct = TestGI.SimpleStruct() + struct.long_ = 6 + struct.int8 = 7 + + struct.method() + + del struct + + self.assertRaises(TypeError, TestGI.SimpleStruct.method) + + + def test_pointer_struct(self): + self.assertTrue(issubclass(TestGI.PointerStruct, gobject.GPointer)) + + struct = TestGI.PointerStruct() + self.assertTrue(isinstance(struct, TestGI.PointerStruct)) + + del struct + + def test_pointer_struct_return(self): + struct = TestGI.pointer_struct_return() + + self.assertTrue(isinstance(struct, TestGI.PointerStruct)) + self.assertEquals(42, struct.long_) + + del struct + + def test_pointer_struct_in(self): + struct = TestGI.PointerStruct() + struct.long_ = 42 + + TestGI.pointer_struct_in(struct) + + del struct + + def test_pointer_struct_out(self): + struct = TestGI.pointer_struct_out() + + self.assertTrue(isinstance(struct, TestGI.PointerStruct)) + self.assertEquals(42, struct.long_) + + del struct + + def test_pointer_struct_inout(self): + in_struct = TestGI.PointerStruct() + in_struct.long_ = 42 + + out_struct = TestGI.pointer_struct_inout(in_struct) + + self.assertTrue(isinstance(out_struct, TestGI.PointerStruct)) + self.assertEquals(0, out_struct.long_) + + del in_struct + del out_struct + + + def test_boxed_struct(self): + self.assertTrue(issubclass(TestGI.BoxedStruct, gobject.GBoxed)) + + self.assertRaises(TypeError, TestGI.BoxedStruct) + + def test_boxed_instantiable_struct(self): + struct = TestGI.BoxedInstantiableStruct() + + self.assertTrue(isinstance(struct, TestGI.BoxedInstantiableStruct)) + + new_struct = struct.copy() + self.assertTrue(isinstance(new_struct, TestGI.BoxedInstantiableStruct)) + + del struct + del new_struct + + def test_boxed_instantiable_struct_return(self): + struct = TestGI.boxed_instantiable_struct_return() + + self.assertTrue(isinstance(struct, TestGI.BoxedInstantiableStruct)) + self.assertEquals(42, struct.long_) + + del struct + + def test_boxed_instantiable_struct_in(self): + struct = TestGI.BoxedInstantiableStruct() + struct.long_ = 42 + + TestGI.boxed_instantiable_struct_in(struct) + + del struct + + def test_boxed_instantiable_struct_out(self): + struct = TestGI.boxed_instantiable_struct_out() + + self.assertTrue(isinstance(struct, TestGI.BoxedInstantiableStruct)) + self.assertEquals(42, struct.long_) + + del struct + + def test_boxed_instantiable_struct_inout(self): + in_struct = TestGI.BoxedInstantiableStruct() + in_struct.long_ = 42 + + out_struct = TestGI.boxed_instantiable_struct_inout(in_struct) + + self.assertTrue(isinstance(out_struct, TestGI.BoxedInstantiableStruct)) + self.assertEquals(0, out_struct.long_) + + del in_struct + del out_struct + + +class TestGObject(unittest.TestCase): + + def test_object(self): + self.assertTrue(issubclass(TestGI.Object, gobject.GObject)) + + object_ = TestGI.Object() + self.assertTrue(isinstance(object_, TestGI.Object)) + self.assertEquals(object_.__grefcount__, 1) + + def test_object_new(self): + object_ = TestGI.Object.new(42) + self.assertTrue(isinstance(object_, TestGI.Object)) + self.assertEquals(object_.__grefcount__, 1) + + def test_object_int(self): + object_ = TestGI.Object(int = 42) + self.assertEquals(object_.int_, 42) +# FIXME: Don't work yet. +# object_.int_ = 0 +# self.assertEquals(object_.int_, 0) + + def test_object_static_method(self): + TestGI.Object.static_method() + + def test_object_method(self): + TestGI.Object(int = 42).method() + self.assertRaises(TypeError, TestGI.Object.method, gobject.GObject()) + self.assertRaises(TypeError, TestGI.Object.method) + + + def test_sub_object(self): + self.assertTrue(issubclass(TestGI.SubObject, TestGI.Object)) + + object_ = TestGI.SubObject() + self.assertTrue(isinstance(object_, TestGI.SubObject)) + + def test_sub_object_new(self): + self.assertRaises(TypeError, TestGI.SubObject.new, 42) + + def test_sub_object_static_method(self): + object_ = TestGI.SubObject() + object_.static_method() + + def test_sub_object_method(self): + object_ = TestGI.SubObject(int = 42) + object_.method() + + def test_sub_object_sub_method(self): + object_ = TestGI.SubObject() + object_.sub_method() + + def test_sub_object_overwritten_method(self): + object_ = TestGI.SubObject() + object_.overwritten_method() + + self.assertRaises(TypeError, TestGI.SubObject.overwritten_method, TestGI.Object()) + + def test_sub_object_int(self): + object_ = TestGI.SubObject() + self.assertEquals(object_.int_, 0) +# FIXME: Don't work yet. +# object_.int_ = 42 +# self.assertEquals(object_.int_, 42) + + def test_object_none_return(self): + object_ = TestGI.object_none_return() + self.assertTrue(isinstance(object_, TestGI.Object)) + self.assertEquals(object_.__grefcount__, 2) + + def test_object_full_return(self): + object_ = TestGI.object_full_return() + self.assertTrue(isinstance(object_, TestGI.Object)) + self.assertEquals(object_.__grefcount__, 1) + + def test_object_none_in(self): + object_ = TestGI.Object(int = 42) + TestGI.object_none_in(object_) + self.assertEquals(object_.__grefcount__, 1) + + object_ = TestGI.SubObject(int = 42) + TestGI.object_none_in(object_) + + object_ = gobject.GObject() + self.assertRaises(TypeError, TestGI.object_none_in, object_) + + self.assertRaises(TypeError, TestGI.object_none_in, None) + + def test_object_full_in(self): + object_ = TestGI.Object(int = 42) + TestGI.object_full_in(object_) + self.assertEquals(object_.__grefcount__, 1) + + def test_object_none_out(self): + object_ = TestGI.object_none_out() + self.assertTrue(isinstance(object_, TestGI.Object)) + self.assertEquals(object_.__grefcount__, 2) + + new_object = TestGI.object_none_out() + self.assertTrue(new_object is object_) + + def test_object_full_out(self): + object_ = TestGI.object_full_out() + self.assertTrue(isinstance(object_, TestGI.Object)) + self.assertEquals(object_.__grefcount__, 1) + + def test_object_none_inout(self): + object_ = TestGI.Object(int = 42) + new_object = TestGI.object_none_inout(object_) + + self.assertTrue(isinstance(new_object, TestGI.Object)) + + self.assertFalse(object_ is new_object) + + self.assertEquals(object_.__grefcount__, 1) + self.assertEquals(new_object.__grefcount__, 2) + + new_new_object = TestGI.object_none_inout(object_) + self.assertTrue(new_new_object is new_object) + + TestGI.object_none_inout(TestGI.SubObject(int = 42)) + + def test_object_full_inout(self): + object_ = TestGI.Object(int = 42) + new_object = TestGI.object_full_inout(object_) + + self.assertTrue(isinstance(new_object, TestGI.Object)) + + self.assertFalse(object_ is new_object) + + self.assertEquals(object_.__grefcount__, 1) + self.assertEquals(new_object.__grefcount__, 1) + +# FIXME: Doesn't actually return the same object. +# def test_object_inout_same(self): +# object_ = TestGI.Object() +# new_object = TestGI.object_full_inout(object_) +# self.assertTrue(object_ is new_object) +# self.assertEquals(object_.__grefcount__, 1) + + +class TestMultiOutputArgs(unittest.TestCase): + + def test_int_out_out(self): + self.assertEquals((6, 7), TestGI.int_out_out()) + + def test_int_return_out(self): + self.assertEquals((6, 7), TestGI.int_return_out()) + + -- cgit v1.2.1