[pygobject] Introduces the girepository module from the former PyBank.



commit e4f2a5ef8734cf40cf8345d442612db1f6c62d5a
Author: Simon van der Linden <simon vanderlinden student uclouvain be>
Date:   Thu May 28 17:45:11 2009 +0200

    Introduces the girepository module from the former PyBank.
---
 INSTALL                        |   69 ++-
 Makefile.am                    |    2 +-
 configure.ac                   |   12 +
 girepository/Makefile.am       |   52 ++
 girepository/__init__.py       |   24 +
 girepository/bank-argument.c   |  379 +++++++++++++
 girepository/bank-info.c       | 1194 ++++++++++++++++++++++++++++++++++++++++
 girepository/bank-repository.c |  237 ++++++++
 girepository/bank.c            |  155 ++++++
 girepository/bank.h            |   80 +++
 girepository/btypes.py         |  300 ++++++++++
 girepository/importer.py       |   52 ++
 girepository/module.py         |  224 ++++++++
 girepository/repository.py     |   51 ++
 14 files changed, 2799 insertions(+), 32 deletions(-)

diff --git a/INSTALL b/INSTALL
index 54caf7c..23e5f25 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,13 +1,16 @@
-Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002 Free Software
-Foundation, Inc.
+Installation Instructions
+*************************
 
-   This file is free documentation; the Free Software Foundation gives
+Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005 Free
+Software Foundation, Inc.
+
+This file is free documentation; the Free Software Foundation gives
 unlimited permission to copy, distribute and modify it.
 
 Basic Installation
 ==================
 
-   These are generic installation instructions.
+These are generic installation instructions.
 
    The `configure' shell script attempts to guess correct values for
 various system-dependent variables used during compilation.  It uses
@@ -67,9 +70,9 @@ The simplest way to compile this package is:
 Compilers and Options
 =====================
 
-   Some systems require unusual options for compilation or linking that
-the `configure' script does not know about.  Run `./configure --help'
-for details on some of the pertinent environment variables.
+Some systems require unusual options for compilation or linking that the
+`configure' script does not know about.  Run `./configure --help' for
+details on some of the pertinent environment variables.
 
    You can give `configure' initial values for configuration parameters
 by setting variables in the command line or in the environment.  Here
@@ -82,7 +85,7 @@ is an example:
 Compiling For Multiple Architectures
 ====================================
 
-   You can compile the package for more than one kind of computer at the
+You can compile the package for more than one kind of computer at the
 same time, by placing the object files for each architecture in their
 own directory.  To do this, you must use a version of `make' that
 supports the `VPATH' variable, such as GNU `make'.  `cd' to the
@@ -99,19 +102,19 @@ for another architecture.
 Installation Names
 ==================
 
-   By default, `make install' will install the package's files in
-`/usr/local/bin', `/usr/local/man', etc.  You can specify an
-installation prefix other than `/usr/local' by giving `configure' the
-option `--prefix=PATH'.
+By default, `make install' installs the package's commands under
+`/usr/local/bin', include files under `/usr/local/include', etc.  You
+can specify an installation prefix other than `/usr/local' by giving
+`configure' the option `--prefix=PREFIX'.
 
    You can specify separate installation prefixes for
 architecture-specific files and architecture-independent files.  If you
-give `configure' the option `--exec-prefix=PATH', the package will use
-PATH as the prefix for installing programs and libraries.
-Documentation and other data files will still use the regular prefix.
+pass the option `--exec-prefix=PREFIX' to `configure', the package uses
+PREFIX as the prefix for installing programs and libraries.
+Documentation and other data files still use the regular prefix.
 
    In addition, if you use an unusual directory layout you can give
-options like `--bindir=PATH' to specify different values for particular
+options like `--bindir=DIR' to specify different values for particular
 kinds of files.  Run `configure --help' for a list of the directories
 you can set and what kinds of files go in them.
 
@@ -122,7 +125,7 @@ option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
 Optional Features
 =================
 
-   Some packages pay attention to `--enable-FEATURE' options to
+Some packages pay attention to `--enable-FEATURE' options to
 `configure', where FEATURE indicates an optional part of the package.
 They may also pay attention to `--with-PACKAGE' options, where PACKAGE
 is something like `gnu-as' or `x' (for the X Window System).  The
@@ -137,11 +140,11 @@ you can use the `configure' options `--x-includes=DIR' and
 Specifying the System Type
 ==========================
 
-   There may be some features `configure' cannot figure out
-automatically, but needs to determine by the type of machine the package
-will run on.  Usually, assuming the package is built to be run on the
-_same_ architectures, `configure' can figure that out, but if it prints
-a message saying it cannot guess the machine type, give it the
+There may be some features `configure' cannot figure out automatically,
+but needs to determine by the type of machine the package will run on.
+Usually, assuming the package is built to be run on the _same_
+architectures, `configure' can figure that out, but if it prints a
+message saying it cannot guess the machine type, give it the
 `--build=TYPE' option.  TYPE can either be a short name for the system
 type, such as `sun4', or a canonical name which has the form:
 
@@ -156,7 +159,7 @@ where SYSTEM can have one of these forms:
 need to know the machine type.
 
    If you are _building_ compiler tools for cross-compiling, you should
-use the `--target=TYPE' option to select the type of system they will
+use the option `--target=TYPE' to select the type of system they will
 produce code for.
 
    If you want to _use_ a cross compiler, that generates code for a
@@ -167,9 +170,9 @@ eventually be run) with `--host=TYPE'.
 Sharing Defaults
 ================
 
-   If you want to set default values for `configure' scripts to share,
-you can create a site shell script called `config.site' that gives
-default values for variables like `CC', `cache_file', and `prefix'.
+If you want to set default values for `configure' scripts to share, you
+can create a site shell script called `config.site' that gives default
+values for variables like `CC', `cache_file', and `prefix'.
 `configure' looks for `PREFIX/share/config.site' if it exists, then
 `PREFIX/etc/config.site' if it exists.  Or, you can set the
 `CONFIG_SITE' environment variable to the location of the site script.
@@ -178,7 +181,7 @@ A warning: not all `configure' scripts look for a site script.
 Defining Variables
 ==================
 
-   Variables not defined in a site shell script can be set in the
+Variables not defined in a site shell script can be set in the
 environment passed to `configure'.  However, some packages may run
 configure again during the build, and the customized values of these
 variables may be lost.  In order to avoid this problem, you should set
@@ -186,14 +189,18 @@ them in the `configure' command line, using `VAR=value'.  For example:
 
      ./configure CC=/usr/local2/bin/gcc
 
-will cause the specified gcc to be used as the C compiler (unless it is
-overridden in the site shell script).
+causes the specified `gcc' to be used as the C compiler (unless it is
+overridden in the site shell script).  Here is a another example:
+
+     /bin/bash ./configure CONFIG_SHELL=/bin/bash
+
+Here the `CONFIG_SHELL=/bin/bash' operand causes subsequent
+configuration-related scripts to be executed by `/bin/bash'.
 
 `configure' Invocation
 ======================
 
-   `configure' recognizes the following options to control how it
-operates.
+`configure' recognizes the following options to control how it operates.
 
 `--help'
 `-h'
diff --git a/Makefile.am b/Makefile.am
index 93442af..41e29af 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,7 +1,7 @@
 ACLOCAL_AMFLAGS = -I m4
 AUTOMAKE_OPTIONS = 1.7
 
-SUBDIRS = docs codegen glib gobject gio examples tests
+SUBDIRS = docs codegen glib gobject gio girepository examples tests
 
 PLATFORM_VERSION = 2.0
 
diff --git a/configure.ac b/configure.ac
index acd269e..ed1f1a3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -11,6 +11,7 @@ dnl versions of packages we require ...
 m4_define(glib_required_version, 2.14.0)
 m4_define(gio_required_version, 2.16.0)
 m4_define(giounix_required_version, 2.16.0)
+m4_define(gobject_introspection_required_version, 0.6.3)
 
 AC_INIT(pygobject, pygobject_version,
         [http://bugzilla.gnome.org/enter_bug.cgi?product=pygobject])
@@ -199,6 +200,16 @@ if test -n "$export_dynamic"; then
   GIOUNIX_LIBS=`echo $GIOUNIX_LIBS | sed -e "s/$export_dynamic//"`
 fi
 
+dnl gobject_introspection
+PKG_CHECK_MODULES(GOBJECT_INTROSPECTION, gobject-introspection-1.0 >= gobject_introspection_required_version,
+	have_gobject_introspection=true, have_gobject_introspection=false)
+AC_SUBST(GOBJECT_INTROSPECTION_CFLAGS)
+AC_SUBST(GOBJECT_INTROSPECTION_LIBS)
+AM_CONDITIONAL(BUILD_GOBJECT_INTROSPECTION, $have_gobject_introspection)
+if test -n "$export_dynamic"; then
+  GOBJECT_INTROSPECTION_LIBS=`echo $GOBJECT_INTROSPECTION_LIBS | sed -e "s/$export_dynamic//"`
+fi
+
 dnl add required cflags ...
 if test "x$GCC" = "xyes"; then
   JH_ADD_CFLAG([-Wall])
@@ -226,6 +237,7 @@ AC_CONFIG_FILES(
   glib/Makefile
   gobject/Makefile
   gio/Makefile
+  girepository/Makefile
   examples/Makefile
   tests/Makefile
   PKG-INFO)
diff --git a/girepository/Makefile.am b/girepository/Makefile.am
new file mode 100644
index 0000000..656795d
--- /dev/null
+++ b/girepository/Makefile.am
@@ -0,0 +1,52 @@
+AUTOMAKE_OPTIONS = 1.7
+PLATFORM_VERSION = 2.0
+
+INCLUDES = \
+	-I$(top_srcdir)/gobject \
+	$(PYTHON_INCLUDES) \
+	$(PYGOBJECT_CFLAGS) \
+	$(GOBJECT_INTROSPECTION_CFLAGS)
+
+pkginclude_HEADERS = bank.h
+
+# girepository extension modules
+pkgpyexecdir = $(pyexecdir)/gtk-2.0/girepository
+
+# girepository python scripts
+pygirepositorydir = $(pkgpyexecdir)
+pygirepository_PYTHON = \
+	__init__.py \
+	importer.py \
+	module.py \
+	repository.py \
+	btypes.py
+
+# linker flags
+common_ldflags = -module -avoid-version
+if PLATFORM_WIN32
+common_ldflags += -no-undefined
+endif
+
+CLEANFILES =
+EXTRA_DIST = 
+
+# repo module
+repo_la_CFLAGS = -O0
+repo_la_LDFLAGS = $(common_ldflags) -export-symbols-regex initrepo
+repo_la_LIBADD = $(GOBJECT_INTROSPECTION_LIBS)
+repo_la_SOURCES = \
+	bank-repository.c \
+	bank-argument.c \
+	bank-info.c \
+	bank.c \
+	bank.h
+
+if BUILD_GOBJECT_INTROSPECTION
+pygirepository_LTLIBRARIES = repo.la
+
+all: $(pygirepository_LTLIBRARIES:.la=.so)
+clean-local:
+	rm -f $(pygirepository_LTLIBRARIES:.la=.so)
+.la.so:
+	$(LN_S) .libs/$@ $@ || true
+endif
diff --git a/girepository/__init__.py b/girepository/__init__.py
new file mode 100644
index 0000000..f2e58bf
--- /dev/null
+++ b/girepository/__init__.py
@@ -0,0 +1,24 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+#
+# Copyright (C) 2005, 2007  Johan Dahlin <johan gnome org>
+#
+# 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 .importer import install_importhook
+
+install_importhook()
+
+del install_importhook
diff --git a/girepository/bank-argument.c b/girepository/bank-argument.c
new file mode 100644
index 0000000..9ac28cd
--- /dev/null
+++ b/girepository/bank-argument.c
@@ -0,0 +1,379 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 sw=4 noet ai cindent :
+ *
+ * Copyright (C) 2005  Johan Dahlin <johan gnome org>
+ *
+ * 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 "bank.h"
+#include <pygobject.h>
+
+GArgument
+pyg_argument_from_pyobject(PyObject *object, GITypeInfo *type_info)
+{
+    GArgument arg;
+    GITypeTag type_tag;
+    GIBaseInfo* interface_info;
+    GIInfoType interface_type;
+
+    type_tag = g_type_info_get_tag((GITypeInfo*)type_info);
+    switch (type_tag) {
+    case GI_TYPE_TAG_VOID:
+        /* Nothing to do */
+        break;
+    case GI_TYPE_TAG_UTF8:
+        if (object == Py_None)
+            arg.v_pointer = NULL;
+        else
+            arg.v_pointer = PyString_AsString(object);
+        break;
+    case GI_TYPE_TAG_UINT8:
+        arg.v_uint8 = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_UINT:
+        arg.v_uint = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_UINT16:
+        arg.v_uint16 = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_UINT32:
+        arg.v_uint32 = PyLong_AsLongLong(object);
+        break;
+    case GI_TYPE_TAG_UINT64:
+        if (PyInt_Check(object)) {
+            PyObject *long_obj = PyNumber_Long(object);
+            arg.v_uint64 = PyLong_AsUnsignedLongLong(long_obj);
+            Py_DECREF(long_obj);
+        } else
+            arg.v_uint64 = PyLong_AsUnsignedLongLong(object);
+        break;
+    case GI_TYPE_TAG_INT8:
+        arg.v_int8 = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_INT:
+        arg.v_int = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_LONG:
+        arg.v_long = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_ULONG:
+        arg.v_ulong = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_BOOLEAN:
+        arg.v_boolean = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_INT16:
+        arg.v_int16 = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_INT32:
+        arg.v_int32 = PyInt_AsLong(object);
+        break;
+    case GI_TYPE_TAG_INT64:
+        arg.v_int64 = PyLong_AsLongLong(object);
+        break;
+    case GI_TYPE_TAG_FLOAT:
+        arg.v_float = (float)PyFloat_AsDouble(object);
+        break;
+    case GI_TYPE_TAG_DOUBLE:
+        arg.v_double = PyFloat_AsDouble(object);
+        break;
+    case GI_TYPE_TAG_INTERFACE:
+        interface_info = g_type_info_get_interface(type_info);
+        interface_type = g_base_info_get_type(interface_info);
+        if (interface_type == GI_INFO_TYPE_ENUM) {
+            arg.v_int = PyInt_AsLong(object);
+        } else if (object == Py_None)
+            arg.v_pointer = NULL;
+        else
+            arg.v_pointer = pygobject_get(object);
+        break;
+    case GI_TYPE_TAG_ARRAY:
+        arg.v_pointer = NULL;
+        break;
+    case GI_TYPE_TAG_ERROR:
+        /* Allow NULL GError, otherwise fall through */
+        if (object == Py_None) {
+            arg.v_pointer = NULL;
+            break;
+        }
+    default:
+        g_print("<PyO->GArg> GITypeTag %s is unhandled\n",
+                g_type_tag_to_string(type_tag));
+        break;
+    }
+
+    return arg;
+}
+
+static PyObject *
+glist_to_pyobject(GITypeTag list_tag, GITypeInfo *type_info, GList *list, GSList *slist)
+{
+    PyObject *py_list;
+    int i;
+    GArgument arg;
+    PyObject *child_obj;
+
+    if ((py_list = PyList_New(0)) == NULL) {
+        g_list_free(list);
+        return NULL;
+    }
+    i = 0;
+    if (list_tag == GI_TYPE_TAG_GLIST) {
+        for ( ; list != NULL; list = list->next) {
+            arg.v_pointer = list->data;
+
+            child_obj = pyg_argument_to_pyobject(&arg, type_info);
+
+            if (child_obj == NULL) {
+                g_list_free(list);
+                Py_DECREF(py_list);
+                return NULL;
+            }
+            PyList_Append(py_list, child_obj);
+            Py_DECREF(child_obj);
+
+            ++i;
+        }
+    } else {
+        for ( ; slist != NULL; slist = slist->next) {
+            arg.v_pointer = slist->data;
+
+            child_obj = pyg_argument_to_pyobject(&arg, type_info);
+
+            if (child_obj == NULL) {
+                g_list_free(list);
+                Py_DECREF(py_list);
+                return NULL;
+            }
+            PyList_Append(py_list, child_obj);
+            Py_DECREF(child_obj);
+
+            ++i;
+        }
+    }
+    g_list_free(list);
+    return py_list;
+}
+
+PyObject *
+pyarray_to_pyobject(gpointer array, int length, GITypeInfo *type_info)
+{
+    PyObject *py_list;
+    PyObject *child_obj;
+    GITypeInfo *element_type = g_type_info_get_param_type (type_info, 0);
+    GITypeTag type_tag = g_type_info_get_tag(element_type);
+    gsize size;
+    char buf[256];
+    int i;
+
+    if (array == NULL)
+        return Py_None;
+
+    // FIXME: Doesn't seem right to have this here:
+    switch (type_tag) {
+    case GI_TYPE_TAG_INT:
+        size = sizeof(int);
+        break;
+    case GI_TYPE_TAG_INTERFACE:
+        size = sizeof(gpointer);
+        break;
+    default:
+        snprintf(buf, sizeof(buf), "Unimplemented type: %s\n", g_type_tag_to_string(type_tag));
+        PyErr_SetString(PyExc_TypeError, buf);
+        return NULL;
+    }
+
+    if ((py_list = PyList_New(0)) == NULL) {
+        return NULL;
+    }
+
+    for( i = 0; i < length; i++ ) {
+        gpointer current_element = array + i * size;
+
+        child_obj = pyg_argument_to_pyobject((GArgument *)&current_element, element_type);
+        if (child_obj == NULL) {
+            Py_DECREF(py_list);
+            return NULL;
+        }
+        PyList_Append(py_list, child_obj);
+        Py_DECREF(child_obj);
+    }
+
+    return py_list;
+}
+
+PyObject *
+pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
+{
+    GITypeTag type_tag;
+    PyObject *obj;
+    GIBaseInfo* interface_info;
+    GIInfoType interface_type;
+    GITypeInfo *param_info;
+
+    g_return_val_if_fail(type_info != NULL, NULL);
+    type_tag = g_type_info_get_tag(type_info);
+
+    switch (type_tag) {
+    case GI_TYPE_TAG_VOID:
+        // TODO: Should we take this as a buffer?
+        g_warning("pybank doesn't know what to do with void types");
+        obj = Py_None;
+        break;
+    case GI_TYPE_TAG_GLIST:
+    case GI_TYPE_TAG_GSLIST:
+        param_info = g_type_info_get_param_type(type_info, 0);
+        g_assert(param_info != NULL);
+        obj = glist_to_pyobject(type_tag,
+                                param_info,
+                                type_tag == GI_TYPE_TAG_GLIST ? arg->v_pointer : NULL,
+                                type_tag == GI_TYPE_TAG_GSLIST ? arg->v_pointer : NULL);
+        break;
+    case GI_TYPE_TAG_BOOLEAN:
+        obj = PyBool_FromLong(arg->v_boolean);
+        break;
+    case GI_TYPE_TAG_UINT8:
+        obj = PyInt_FromLong(arg->v_uint8);
+        break;
+    case GI_TYPE_TAG_UINT:
+        obj = PyInt_FromLong(arg->v_uint);
+        break;
+    case GI_TYPE_TAG_UINT16:
+        obj = PyInt_FromLong(arg->v_uint16);
+        break;
+    case GI_TYPE_TAG_UINT32:
+        obj = PyLong_FromLongLong(arg->v_uint32);
+        break;
+    case GI_TYPE_TAG_UINT64:
+        obj = PyLong_FromUnsignedLongLong(arg->v_uint64);
+        break;
+    case GI_TYPE_TAG_INT:
+        obj = PyInt_FromLong(arg->v_int);
+        break;
+    case GI_TYPE_TAG_LONG:
+        obj = PyInt_FromLong(arg->v_long);
+        break;
+    case GI_TYPE_TAG_ULONG:
+        obj = PyInt_FromLong(arg->v_ulong);
+        break;
+    case GI_TYPE_TAG_INT8:
+        obj = PyInt_FromLong(arg->v_int8);
+        break;
+    case GI_TYPE_TAG_INT16:
+        obj = PyInt_FromLong(arg->v_int16);
+        break;
+    case GI_TYPE_TAG_INT32:
+        obj = PyInt_FromLong(arg->v_int32);
+        break;
+    case GI_TYPE_TAG_INT64:
+        obj = PyLong_FromLongLong(arg->v_int64);
+        break;
+    case GI_TYPE_TAG_FLOAT:
+        obj = PyFloat_FromDouble(arg->v_float);
+        break;
+    case GI_TYPE_TAG_DOUBLE:
+        obj = PyFloat_FromDouble(arg->v_double);
+        break;
+    case GI_TYPE_TAG_UTF8:
+        if (arg->v_string == NULL)
+            obj = Py_None;
+        else
+            obj = PyString_FromString(arg->v_string);
+        break;
+    case GI_TYPE_TAG_INTERFACE:
+        interface_info = g_type_info_get_interface(type_info);
+        interface_type = g_base_info_get_type(interface_info);
+
+        if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
+            // Create new struct based on arg->v_pointer
+            const gchar *module_name = g_base_info_get_namespace(interface_info);
+            const gchar *type_name = g_base_info_get_name(interface_info);
+            PyObject *module = PyImport_ImportModule(module_name);
+            PyObject *tp = PyObject_GetAttrString(module, type_name);
+            gsize size;
+            PyObject *buffer;
+            PyObject **dict;
+
+            if (tp == NULL) {
+                char buf[256];
+                snprintf(buf, sizeof(buf), "Type %s.%s not defined", module_name, type_name);
+                PyErr_SetString(PyExc_TypeError, buf);
+                return NULL;
+            }
+
+            obj = PyObject_GC_New(PyObject, (PyTypeObject *) tp);
+            if (obj == NULL)
+                return NULL;
+
+            // FIXME: Any better way to initialize the dict pointer?
+            dict = (PyObject **) ((char *)obj + ((PyTypeObject *) tp)->tp_dictoffset);
+            *dict = NULL;
+
+            size = g_struct_info_get_size ((GIStructInfo*)interface_info);
+            buffer = PyBuffer_FromReadWriteMemory(arg->v_pointer, size);
+            if (buffer == NULL)
+                return NULL;
+
+            PyObject_SetAttrString(obj, "__buffer__", buffer);
+
+        } else if (interface_type == GI_INFO_TYPE_ENUM) {
+	    obj = PyInt_FromLong(arg->v_int);
+        } else if ( arg->v_pointer == NULL ) {
+            obj = Py_None;
+        } else {
+            GValue value;
+            GObject* gobj = arg->v_pointer;
+            GType gtype = G_OBJECT_TYPE(gobj);
+            GIRepository *repo = g_irepository_get_default();
+            GIBaseInfo *object_info = g_irepository_find_by_gtype(repo, gtype);
+            const gchar *module_name;
+            const gchar *type_name;
+
+            if (object_info != NULL) {
+                // It's a pybank class, we should make sure it is initialized.
+
+                module_name = g_base_info_get_namespace(object_info);
+                type_name = g_base_info_get_name(object_info);
+
+                // This will make sure the wrapper class is registered.
+                char buf[250];
+                snprintf(buf, sizeof(buf), "%s.%s", module_name, type_name);
+                PyRun_SimpleString(buf);
+            }
+
+            value.g_type = gtype;
+            value.data[0].v_pointer = gobj;
+            obj = pyg_value_as_pyobject(&value, FALSE);
+        }
+        break;
+    case GI_TYPE_TAG_ARRAY:
+        g_warning("pyg_argument_to_pyobject: use pyarray_to_pyobject instead for arrays");
+        obj = Py_None;
+        break;
+    default:
+        g_print("<GArg->PyO> GITypeTag %s is unhandled\n",
+                g_type_tag_to_string(type_tag));
+        obj = PyString_FromString("<unhandled return value!>"); /*  */
+        break;
+    }
+
+    if (obj != NULL)
+        Py_INCREF(obj);
+
+    return obj;
+}
+
+
diff --git a/girepository/bank-info.c b/girepository/bank-info.c
new file mode 100644
index 0000000..974d586
--- /dev/null
+++ b/girepository/bank-info.c
@@ -0,0 +1,1194 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 sw=4 noet ai cindent :
+ *
+ * Copyright (C) 2005  Johan Dahlin <johan gnome org>
+ *
+ * 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 "bank.h"
+#include <pygobject.h>
+
+static void      pyg_base_info_dealloc(PyGIBaseInfo *self);
+static void      pyg_base_info_free(PyObject *op);
+static PyObject* pyg_base_info_repr(PyGIBaseInfo *self);
+static int       pyg_base_info_traverse(PyGIBaseInfo *self,
+                                        visitproc visit,
+                                        void *arg);
+static void      pyg_base_info_clear(PyGIBaseInfo *self);
+
+static PyObject *
+_wrap_g_object_info_get_methods(PyGIBaseInfo *self);
+
+#define NEW_CLASS(name, cname) \
+static PyMethodDef _Py##cname##_methods[];    \
+PyTypeObject Py##cname##_Type = {             \
+    PyObject_HEAD_INIT(NULL)                  \
+    0,                                        \
+    "bank." name,                             \
+    sizeof(PyGIBaseInfo),                     \
+    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,             \
+    0, 0, 0, 0, 0, 0,                         \
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, \
+    NULL, 0, 0, 0,                            \
+    offsetof(PyGIBaseInfo, weakreflist),      \
+    0, 0,                                     \
+    _Py##cname##_methods,                     \
+    0, 0, NULL, NULL, 0, 0,                   \
+    offsetof(PyGIBaseInfo, instance_dict)     \
+}
+
+static PyMethodDef _PyGIBaseInfo_methods[];
+static PyGetSetDef _PyGIBaseInfo_getsets[];
+
+PyTypeObject PyGIBaseInfo_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,
+    "bank.BaseInfo",
+    sizeof(PyGIBaseInfo),
+    0,
+    /* methods */
+    (destructor)pyg_base_info_dealloc,
+    (printfunc)0,
+    (getattrfunc)0,
+    (setattrfunc)0,
+    (cmpfunc)0,
+    (reprfunc)pyg_base_info_repr,
+    0,
+    0,
+    0,
+    (hashfunc)0,
+    (ternaryfunc)0,
+    (reprfunc)0,
+    (getattrofunc)0,
+    (setattrofunc)0,
+    0,
+    Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE |
+    Py_TPFLAGS_HAVE_GC,
+    NULL,
+    (traverseproc)pyg_base_info_traverse,
+    (inquiry)pyg_base_info_clear,
+    (richcmpfunc)0,
+    offsetof(PyGIBaseInfo, weakreflist),
+    (getiterfunc)0,
+    (iternextfunc)0,
+    _PyGIBaseInfo_methods,
+    0,
+    _PyGIBaseInfo_getsets,
+    NULL,
+    NULL,
+    (descrgetfunc)0,
+    (descrsetfunc)0,
+    offsetof(PyGIBaseInfo, instance_dict),
+    (initproc)0,
+    (allocfunc)0,                       /* tp_alloc */
+    (newfunc)0,                         /* tp_new */
+    (freefunc)pyg_base_info_free,       /* tp_free */
+    (inquiry)0,                         /* tp_is_gc */
+    (PyObject *)0,                      /* tp_bases */
+};
+
+static PyObject *
+pyg_base_info_repr(PyGIBaseInfo *self)
+{
+    gchar buf[256];
+
+    g_snprintf(buf, sizeof(buf),
+               "<%s object (%s) at 0x%lx>",
+               self->ob_type->tp_name,
+               g_base_info_get_name(self->info), (long)self);
+    return PyString_FromString(buf);
+}
+
+static void
+pyg_base_info_dealloc(PyGIBaseInfo *self)
+{
+    PyObject_ClearWeakRefs((PyObject *)self);
+    pyg_base_info_clear(self);
+}
+
+static int
+pyg_base_info_traverse(PyGIBaseInfo *self,
+                       visitproc visit,
+                       void *arg)
+{
+    int ret = 0;
+
+    if (self->instance_dict)
+        ret = visit(self->instance_dict, arg);
+
+    if (ret != 0)
+        return ret;
+
+    return 0;
+
+}
+
+static void
+pyg_base_info_clear(PyGIBaseInfo *self)
+{
+    PyObject_GC_UnTrack((PyObject *)self);
+
+    Py_CLEAR(self->instance_dict);
+
+    if (self->info) {
+        g_base_info_unref(self->info);
+        self->info = NULL;
+    }
+
+    PyObject_GC_Del(self);
+}
+
+static void
+pyg_base_info_free(PyObject *op)
+{
+    PyObject_GC_Del(op);
+}
+
+
+static PyObject *
+pyg_base_info_get_dict(PyGIBaseInfo *self, void *closure)
+{
+    if (self->instance_dict == NULL) {
+        self->instance_dict = PyDict_New();
+        if (self->instance_dict == NULL)
+            return NULL;
+    }
+    Py_INCREF(self->instance_dict);
+    return self->instance_dict;
+}
+
+static PyGetSetDef _PyGIBaseInfo_getsets[] = {
+    { "__dict__", (getter)pyg_base_info_get_dict, (setter)0 },
+    { NULL, 0, 0 }
+};
+
+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_type(PyGIBaseInfo *self)
+{
+    return PyInt_FromLong(g_base_info_get_type(self->info));
+}
+
+PyObject *
+pyg_info_new(void *info)
+{
+    PyGIBaseInfo *self;
+    GIInfoType type_info;
+    PyTypeObject *tp;
+
+    if (info == NULL) {
+        PyErr_SetString(PyExc_TypeError, "NULL value sent to pyg_info_new");
+        return NULL;
+    }
+
+    type_info = g_base_info_get_type((GIBaseInfo*)info);
+
+    switch (type_info)
+        {
+        case GI_INFO_TYPE_OBJECT:
+            tp = &PyGIObjectInfo_Type;
+            break;
+        case GI_INFO_TYPE_BOXED:
+            tp = &PyGIBoxedInfo_Type;
+            break;
+        case GI_INFO_TYPE_STRUCT:
+            tp = &PyGIStructInfo_Type;
+            break;
+        case GI_INFO_TYPE_FUNCTION:
+            tp = &PyGIFunctionInfo_Type;
+            break;
+        case GI_INFO_TYPE_ENUM:
+        case GI_INFO_TYPE_FLAGS:
+            tp = &PyGIEnumInfo_Type;
+            break;
+        case GI_INFO_TYPE_ARG:
+            tp = &PyGIArgInfo_Type;
+            break;
+        case GI_INFO_TYPE_TYPE:
+            tp = &PyGITypeInfo_Type;
+            break;
+        case GI_INFO_TYPE_INTERFACE:
+            tp = &PyGIInterfaceInfo_Type;
+            break;
+        case GI_INFO_TYPE_UNRESOLVED:
+            tp = &PyGIUnresolvedInfo_Type;
+            break;
+        case GI_INFO_TYPE_VALUE:
+            tp = &PyGIValueInfo_Type;
+            break;
+        case GI_INFO_TYPE_FIELD:
+            tp = &PyGIFieldInfo_Type;
+            break;
+        default:
+            g_print ("Unhandled GIInfoType: %d\n", type_info);
+            Py_INCREF(Py_None);
+            return Py_None;
+        }
+
+    if (tp->tp_flags & Py_TPFLAGS_HEAPTYPE)
+        Py_INCREF(tp);
+
+    self = (PyGIBaseInfo*)PyObject_GC_New(PyGIBaseInfo, tp);
+    if (self == NULL)
+        return NULL;
+
+    self->info = g_base_info_ref(info);
+
+    self->instance_dict = NULL;
+    self->weakreflist = NULL;
+
+    PyObject_GC_Track((PyObject *)self);
+
+    return (PyObject*)self;
+}
+
+static PyMethodDef _PyGIBaseInfo_methods[] = {
+    { "getName", (PyCFunction)_wrap_g_base_info_get_name, METH_NOARGS },
+    { "getType", (PyCFunction)_wrap_g_base_info_get_type, METH_NOARGS },
+    { "getNamespace", (PyCFunction)_wrap_g_base_info_get_namespace, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+
+/* CallableInfo */
+NEW_CLASS("CallableInfo", GICallableInfo);
+
+static PyObject *
+_wrap_g_callable_info_get_args(PyGIBaseInfo *self)
+{
+    int i, length;
+    PyObject *retval;
+
+    length = g_callable_info_get_n_args((GICallableInfo*)self->info);
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++) {
+        GIArgInfo *arg;
+        arg = g_callable_info_get_arg((GICallableInfo*)self->info, i);
+        PyTuple_SetItem(retval, i, pyg_info_new(arg));
+        g_base_info_unref((GIBaseInfo*)arg);
+    }
+
+    return retval;
+}
+
+static PyObject *
+_wrap_g_callable_info_get_return_type(PyGIBaseInfo *self)
+{
+    return pyg_info_new(g_callable_info_get_return_type((GICallableInfo*)self->info));
+}
+
+static PyMethodDef _PyGICallableInfo_methods[] = {
+    { "getArgs", (PyCFunction)_wrap_g_callable_info_get_args, METH_NOARGS },
+    { "getReturnType", (PyCFunction)_wrap_g_callable_info_get_return_type, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+/* FunctionInfo */
+NEW_CLASS("FunctionInfo", GIFunctionInfo);
+
+static PyObject *
+_wrap_g_function_info_is_constructor(PyGIBaseInfo *self)
+{
+    return PyInt_FromLong(g_function_info_get_flags((GIFunctionInfo*)self->info) &
+                          GI_FUNCTION_IS_CONSTRUCTOR);
+}
+
+static PyObject *
+_wrap_g_function_info_is_method(PyGIBaseInfo *self)
+{
+    return PyInt_FromLong(g_function_info_get_flags((GIFunctionInfo*)self->info) &
+                          GI_FUNCTION_IS_METHOD);
+}
+
+static PyObject *
+_wrap_g_function_info_invoke(PyGIBaseInfo *self, PyObject *args)
+{
+    GArgument *in_args;
+    GArgument *out_args;
+    GArgument *out_values;
+    GArgument return_arg;
+    int n_args;
+    int expected_in_argc;
+    int expected_out_argc;
+    int i;
+    int argv_pos;
+    int in_args_pos;
+    int out_args_pos;
+    GError *error;
+    gboolean failed;
+    GIFunctionInfoFlags flags;
+    gboolean is_method;
+    gboolean is_constructor;
+    gboolean invoke_ok;
+    GITypeInfo *return_info;
+    GITypeTag return_tag;
+    PyObject **return_values;
+    int n_return_values;
+    int next_rval;
+    PyObject *retval;
+    PyObject *py_arg;
+
+    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;
+
+    expected_in_argc = 0;
+    expected_out_argc = 0;
+
+    n_args = g_callable_info_get_n_args( (GICallableInfo*) self->info);
+    for (i = 0; i < n_args; i++) {
+        GIDirection direction;
+        GIArgInfo *arg_info;
+
+        arg_info = g_callable_info_get_arg( (GICallableInfo*) self->info, i);
+        direction = g_arg_info_get_direction(arg_info);
+        if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
+            expected_in_argc += 1;
+        if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
+            expected_out_argc += 1;
+        g_base_info_unref( (GIBaseInfo*) arg_info);
+    }
+    /*
+    g_debug("Call is to %s %s.%s with expected: %d in args, %d out args, %d total args",
+                      is_method ? "method" : "function",
+                      g_base_info_get_namespace( (GIBaseInfo*) self->info),
+                      g_base_info_get_name( (GIBaseInfo*) self->info),
+                      expected_in_argc,
+                      expected_out_argc,
+                      n_args);
+    */
+    if (is_method)
+        expected_in_argc += 1;
+
+    in_args = g_newa(GArgument, expected_in_argc);
+    out_args = g_newa(GArgument, expected_out_argc);
+    /* each out arg is a pointer, they point to these values */
+    /* FIXME: This will break for caller-allocates funcs:
+       http://bugzilla.gnome.org/show_bug.cgi?id=573314 */
+    out_values = g_newa(GArgument, expected_out_argc);
+
+    failed = FALSE;
+    in_args_pos = 0; /* index into in_args */
+    out_args_pos = 0; /* into out_args */
+    argv_pos = 0; /* index into argv */
+
+    if (is_method && !is_constructor) {
+        GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) self->info);
+        GIInfoType type = g_base_info_get_type(container);
+
+        py_arg = PyTuple_GetItem(args, 0);
+        if (!py_arg) {
+            PyErr_SetString(PyExc_ValueError, "Calling a method without passing an instance");
+            return NULL;
+        }
+        if (py_arg == Py_None) {
+            in_args[0].v_pointer = NULL;
+        } else if (type == GI_INFO_TYPE_STRUCT || type == GI_INFO_TYPE_BOXED) {
+            PyObject *pybuffer = PyObject_GetAttrString((PyObject *)py_arg,
+                                                        "__buffer__");
+            PyBufferProcs *buffer_procs = pybuffer->ob_type->tp_as_buffer;
+            (*buffer_procs->bf_getreadbuffer)(pybuffer, 0, &in_args[0].v_pointer);
+        } else { /* by fallback is always object */
+            in_args[0].v_pointer = pygobject_get(py_arg);
+        }
+        ++in_args_pos;
+    }
+
+    for (i = 0; i < n_args; i++) {
+        GIDirection direction;
+        GIArgInfo *arg_info;
+        GArgument *out_value;
+
+        arg_info = g_callable_info_get_arg( (GICallableInfo*) self->info, i);
+        direction = g_arg_info_get_direction(arg_info);
+
+        out_value = NULL;
+        if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
+            g_assert(out_args_pos < expected_out_argc);
+
+            out_value = &out_values[out_args_pos];
+            out_args[out_args_pos].v_pointer = out_value;
+            ++out_args_pos;
+        }
+
+        if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT) {
+            if (is_method || is_constructor)
+                py_arg = PyTuple_GetItem(args, i + 1);
+            else
+                py_arg = PyTuple_GetItem(args, i);
+
+            GArgument in_value = pyg_argument_from_pyobject(py_arg, g_arg_info_get_type(arg_info));
+
+            ++argv_pos;
+
+            if (direction == GI_DIRECTION_IN) {
+                in_args[in_args_pos] = in_value;
+            } else {
+                /* INOUT means we pass a pointer */
+                g_assert(out_value != NULL);
+                *out_value = in_value;
+                in_args[in_args_pos].v_pointer = out_value;
+            }
+
+            ++in_args_pos;
+        }
+
+        g_base_info_unref( (GIBaseInfo*) arg_info);
+
+        if (failed)
+            break;
+    }
+
+    if (failed) {
+        PyErr_SetString(PyExc_ValueError, "Failed to convert all args.");
+        return NULL;
+    }
+
+    g_assert(in_args_pos == expected_in_argc);
+    g_assert(out_args_pos == expected_out_argc);
+
+    error = NULL;
+    invoke_ok = g_function_info_invoke( (GIFunctionInfo*) self->info,
+                                        in_args, expected_in_argc,
+                                        out_args, expected_out_argc,
+                                        &return_arg,
+                                        &error);
+
+    return_info = g_callable_info_get_return_type( (GICallableInfo*) self->info);
+    g_assert(return_info != NULL);
+
+    if (!invoke_ok) {
+        char buf[256];
+        snprintf(buf, sizeof(buf), "Error invoking %s.%s: %s",
+                 g_base_info_get_namespace( (GIBaseInfo*) self->info),
+                 g_base_info_get_name( (GIBaseInfo*) self->info),
+                 error->message);
+
+        g_assert(error != NULL);
+        PyErr_SetString(PyExc_RuntimeError, buf);
+        g_error_free(error);
+
+        return NULL;
+    }
+
+    return_tag = g_type_info_get_tag(return_info);
+
+    if (is_constructor) {
+        py_arg = PyTuple_GetItem(args, 0);
+
+        if (return_tag == GI_TYPE_TAG_INTERFACE) {
+            GIBaseInfo *interface_info = g_type_info_get_interface(return_info);
+            GIInfoType interface_type = g_base_info_get_type(interface_info);
+
+            if (interface_type == GI_INFO_TYPE_STRUCT || interface_type == GI_INFO_TYPE_BOXED) {
+                // FIXME: We should reuse this. Perhaps by separating the
+                // wrapper creation from the binding to the wrapper.
+                gsize size = g_struct_info_get_size ((GIStructInfo*)return_info);
+                PyObject *buffer = PyBuffer_FromReadWriteMemory(return_arg.v_pointer, size);
+
+                //PyObject *dict = PyObject_GetDict(py_arg);
+                PyObject_SetAttrString(py_arg, "__buffer__", buffer);
+
+                Py_INCREF(py_arg);
+                return py_arg;
+            } else {
+                PyGObject *self = (PyGObject *) py_arg;
+                if (self->obj != NULL) {
+                    PyErr_SetString(PyExc_ValueError, "Calling constructor on an instance that isn't a GObject");
+                    return NULL;
+                }
+                self->obj = return_arg.v_pointer;
+                g_object_ref(return_arg.v_pointer);
+                pygobject_register_wrapper(py_arg);
+                Py_INCREF(py_arg);
+                return py_arg;
+            }
+        } else {
+            PyErr_SetString(PyExc_NotImplementedError, "");
+            return NULL;
+        }
+    }
+
+    retval = NULL;
+
+    next_rval = 0; /* index into return_values */
+
+    n_return_values = expected_out_argc;
+    if (return_tag != GI_TYPE_TAG_VOID)
+        n_return_values += 1;
+
+    return_values = g_newa(PyObject*, n_return_values);
+    if (!is_constructor && n_return_values > 0) {
+        if (return_tag != GI_TYPE_TAG_VOID) {
+            PyObject *obj = pyg_argument_to_pyobject(&return_arg, return_info);
+            if (obj == NULL) {
+                return NULL;
+            }
+            return_values[next_rval] = obj;
+
+            ++next_rval;
+        }
+    }
+
+    /* We walk over all args, release in args (if allocated) and convert
+     * all out args
+     */
+    in_args_pos = is_method ? 1 : 0; /* index into in_args */
+    out_args_pos = 0; /* into out_args */
+
+    for (i = 0; i < n_args; i++) {
+        GIDirection direction;
+        GIArgInfo *arg_info;
+        GITypeInfo *arg_type_info;
+
+        arg_info = g_callable_info_get_arg( (GICallableInfo*) self->info, i);
+        direction = g_arg_info_get_direction(arg_info);
+
+        arg_type_info = g_arg_info_get_type(arg_info);
+
+        if (direction == GI_DIRECTION_IN) {
+            g_assert(in_args_pos < expected_in_argc);
+
+            ++in_args_pos;
+        } else {
+            /* INOUT or OUT */
+            if (direction == GI_DIRECTION_INOUT)
+                g_assert(in_args_pos < expected_in_argc);
+            g_assert(next_rval < n_return_values);
+            g_assert(out_args_pos < expected_out_argc);
+
+            PyObject *obj;
+            GITypeTag type_tag = g_type_info_get_tag(arg_type_info);
+
+            if (type_tag == GI_TYPE_TAG_ARRAY) {
+                GArgument *arg = out_args[out_args_pos].v_pointer;
+                gint length_arg_index = g_type_info_get_array_length(arg_type_info);
+                GArgument *length_arg;
+
+                if (is_method)
+                    length_arg_index--;
+
+                if (length_arg_index == -1) {
+                    PyErr_SetString(PyExc_NotImplementedError, "Need a field to specify the array length");
+                    return NULL;
+                }
+
+                length_arg = out_args[length_arg_index].v_pointer;
+
+                if (length_arg == NULL) {
+                    PyErr_SetString(PyExc_RuntimeError, "Failed to get the length of the array");
+                    return NULL;
+                }
+
+                obj = pyarray_to_pyobject(arg->v_pointer, length_arg->v_int, arg_type_info);
+            } else
+                obj = pyg_argument_to_pyobject(out_args[out_args_pos].v_pointer, arg_type_info);
+            if (obj == NULL) {
+                return NULL;
+            }
+            return_values[next_rval] = obj;
+
+            if (direction == GI_DIRECTION_INOUT)
+                ++in_args_pos;
+
+            ++out_args_pos;
+
+            ++next_rval;
+        }
+
+        g_base_info_unref( (GIBaseInfo*) arg_type_info);
+        g_base_info_unref( (GIBaseInfo*) arg_info);
+    }
+
+    g_assert(next_rval == n_return_values);
+    g_assert(out_args_pos == expected_out_argc);
+    g_assert(in_args_pos == expected_in_argc);
+
+    if (n_return_values > 0) {
+        if (n_return_values == 0) {
+            retval = Py_None;
+            Py_INCREF(retval);
+        } else if (n_return_values == 1) {
+            retval = return_values[0];
+        } else {
+            retval = PyTuple_New(n_return_values);
+            for (i = 0; i < n_return_values; i++) {
+                PyTuple_SetItem(retval, i, return_values[i]);
+            }
+        }
+    }
+
+    g_base_info_unref( (GIBaseInfo*) return_info);
+
+    if (retval == NULL) {
+        Py_INCREF(Py_None);
+        retval = Py_None;
+    }
+
+    return retval;
+}
+
+static PyMethodDef _PyGIFunctionInfo_methods[] = {
+    { "isConstructor", (PyCFunction)_wrap_g_function_info_is_constructor, METH_NOARGS },
+    { "isMethod", (PyCFunction)_wrap_g_function_info_is_method, METH_NOARGS },
+    { "invoke", (PyCFunction)_wrap_g_function_info_invoke, METH_VARARGS },
+    { NULL, NULL, 0 }
+};
+
+/* GICallbackInfo */
+NEW_CLASS("CallbackInfo", GICallbackInfo);
+
+static PyMethodDef _PyGICallbackInfo_methods[] = {
+    { NULL, NULL, 0 }
+};
+
+/* RegisteredTypeInfo */
+NEW_CLASS("RegisteredTypeInfo", GIRegisteredTypeInfo);
+
+static PyObject *
+_wrap_g_registered_type_info_get_g_type (PyGIBaseInfo* self)
+{
+    int gtype;
+
+    gtype = g_registered_type_info_get_g_type ((GIRegisteredTypeInfo*)self->info);
+    return PyInt_FromLong(gtype);
+}
+
+static PyMethodDef _PyGIRegisteredTypeInfo_methods[] = {
+    { "getGType", (PyCFunction)_wrap_g_registered_type_info_get_g_type, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+/* GIStructInfo */
+NEW_CLASS("StructInfo", GIStructInfo);
+
+static PyObject *
+_wrap_g_struct_info_get_fields(PyGIBaseInfo *self)
+{
+    int i, length;
+    PyObject *retval;
+
+    g_base_info_ref(self->info);
+    length = g_struct_info_get_n_fields((GIStructInfo*)self->info);
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++) {
+        GIFieldInfo *field;
+        field = g_struct_info_get_field((GIStructInfo*)self->info, i);
+        PyTuple_SetItem(retval, i, pyg_info_new(field));
+        g_base_info_unref((GIBaseInfo*)field);
+    }
+    g_base_info_unref(self->info);
+
+    return retval;
+}
+
+static PyObject *
+_wrap_g_struct_info_get_methods(PyGIBaseInfo *self)
+{
+    int i, length;
+    PyObject *retval;
+
+    g_base_info_ref(self->info);
+    length = g_struct_info_get_n_methods((GIStructInfo*)self->info);
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++) {
+        GIFunctionInfo *function;
+        function = g_struct_info_get_method((GIStructInfo*)self->info, i);
+        PyTuple_SetItem(retval, i, pyg_info_new(function));
+        g_base_info_unref((GIBaseInfo*)function);
+    }
+    g_base_info_unref(self->info);
+
+    return retval;
+}
+
+static PyObject *
+_wrap_g_struct_info_new_buffer(PyGIBaseInfo *self)
+{
+    gsize size = g_struct_info_get_size ((GIStructInfo*)self->info);
+    PyObject *buffer = PyBuffer_New (size);
+    Py_INCREF(buffer);
+    return buffer;
+}
+
+static PyMethodDef _PyGIStructInfo_methods[] = {
+    { "getFields", (PyCFunction)_wrap_g_struct_info_get_fields, METH_NOARGS },
+    { "getMethods", (PyCFunction)_wrap_g_struct_info_get_methods, METH_NOARGS },
+    { "newBuffer", (PyCFunction)_wrap_g_struct_info_new_buffer, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+/* GIUnionInfo */
+NEW_CLASS("UnionInfo", GIUnionInfo);
+
+static PyMethodDef _PyGIUnionInfo_methods[] = {
+    { NULL, NULL, 0 }
+};
+
+/* EnumInfo */
+NEW_CLASS("EnumInfo", GIEnumInfo);
+
+static PyObject *
+_wrap_g_enum_info_get_values(PyGIBaseInfo *self)
+{
+    int n_values, i;
+    GIValueInfo  *value;
+    PyObject *list;
+
+    g_base_info_ref(self->info);
+    n_values = g_enum_info_get_n_values((GIEnumInfo*)self->info);
+    list = PyList_New(n_values);
+    for (i = 0; i < n_values; i++)
+        {
+            value = g_enum_info_get_value((GIEnumInfo*)self->info, i);
+            PyList_SetItem(list, i, pyg_info_new(value));
+            g_base_info_unref((GIBaseInfo*)value);
+        }
+    g_base_info_unref(self->info);
+
+    return list;
+}
+
+static PyMethodDef _PyGIEnumInfo_methods[] = {
+    { "getValues", (PyCFunction)_wrap_g_enum_info_get_values, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+/* BoxedInfo */
+NEW_CLASS("BoxedInfo", GIBoxedInfo);
+
+static PyMethodDef _PyGIBoxedInfo_methods[] = {
+    { NULL, NULL, 0 }
+};
+
+/* ObjectInfo */
+NEW_CLASS("ObjectInfo", GIObjectInfo);
+
+static PyObject *
+_wrap_g_object_info_get_parent(PyGIBaseInfo *self)
+{
+    GIObjectInfo *parent_info;
+
+    g_base_info_ref(self->info);
+    parent_info = g_object_info_get_parent((GIObjectInfo*)self->info);
+    g_base_info_unref(self->info);
+
+    if (parent_info)
+        return pyg_info_new(parent_info);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyObject *
+_wrap_g_object_info_get_type_name(PyGIBaseInfo *self)
+{
+    const gchar *type_name;
+
+    g_base_info_ref(self->info);
+    type_name = g_object_info_get_type_name((GIObjectInfo*)self->info);
+    g_base_info_unref(self->info);
+
+    return PyString_FromString(type_name);
+}
+
+static PyObject *
+_wrap_g_object_info_get_methods(PyGIBaseInfo *self)
+{
+    int i, length;
+    PyObject *retval;
+
+    g_base_info_ref(self->info);
+    length = g_object_info_get_n_methods((GIObjectInfo*)self->info);
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++) {
+        GIFunctionInfo *function;
+        function = g_object_info_get_method((GIObjectInfo*)self->info, i);
+        PyTuple_SetItem(retval, i, pyg_info_new(function));
+        g_base_info_unref((GIBaseInfo*)function);
+    }
+    g_base_info_unref(self->info);
+
+    return retval;
+}
+
+static PyObject *
+_wrap_g_object_info_get_fields(PyGIBaseInfo *self)
+{
+    int i, length;
+    PyObject *retval;
+
+    g_base_info_ref(self->info);
+    length = g_object_info_get_n_fields((GIObjectInfo*)self->info);
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++) {
+        GIFieldInfo *field;
+        field = g_object_info_get_field((GIObjectInfo*)self->info, i);
+        PyTuple_SetItem(retval, i, pyg_info_new(field));
+        g_base_info_unref((GIBaseInfo*)field);
+    }
+    g_base_info_unref(self->info);
+
+    return retval;
+}
+
+static PyObject *
+_wrap_g_object_info_get_interfaces(PyGIBaseInfo *self)
+{
+    int i, length;
+    PyObject *retval;
+
+    g_base_info_ref(self->info);
+    length = g_object_info_get_n_interfaces((GIObjectInfo*)self->info);
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++) {
+        GIInterfaceInfo *interface;
+        interface = g_object_info_get_interface((GIObjectInfo*)self->info, i);
+        PyTuple_SetItem(retval, i, pyg_info_new(interface));
+        g_base_info_unref((GIBaseInfo*)interface);
+    }
+    g_base_info_unref(self->info);
+
+    return retval;
+}
+
+static PyMethodDef _PyGIObjectInfo_methods[] = {
+    { "getParent", (PyCFunction)_wrap_g_object_info_get_parent, METH_NOARGS },
+    { "getTypeName", (PyCFunction)_wrap_g_object_info_get_type_name, METH_NOARGS },
+    { "getMethods", (PyCFunction)_wrap_g_object_info_get_methods, METH_NOARGS },
+    { "getFields", (PyCFunction)_wrap_g_object_info_get_fields, METH_NOARGS },
+    { "getInterfaces", (PyCFunction)_wrap_g_object_info_get_interfaces, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+
+
+/* GIInterfaceInfo */
+NEW_CLASS("InterfaceInfo", GIInterfaceInfo);
+
+static PyObject *
+_wrap_g_interface_info_get_methods(PyGIBaseInfo *self)
+{
+    int i, length;
+    PyObject *retval;
+
+    g_base_info_ref(self->info);
+    length = g_interface_info_get_n_methods((GIInterfaceInfo*)self->info);
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++) {
+        GIFunctionInfo *function;
+        function = g_interface_info_get_method((GIInterfaceInfo*)self->info, i);
+        PyTuple_SetItem(retval, i, pyg_info_new(function));
+        g_base_info_unref((GIBaseInfo*)function);
+    }
+    g_base_info_unref(self->info);
+
+    return retval;
+}
+
+static void
+initialize_interface (GTypeInterface *iface, PyTypeObject *pytype)
+{
+    // TODO: Implement this when g-i adds supports for vfunc offsets:
+    // http://bugzilla.gnome.org/show_bug.cgi?id=560281
+    /*
+    GIRepository *repo = g_irepository_get_default();
+    GIBaseInfo *iface_info = g_irepository_find_by_gtype(repo, G_TYPE_FROM_INTERFACE(iface));
+    int length, i;
+    GTypeInterface *parent_iface = g_type_interface_peek_parent(iface);
+
+    length = g_interface_info_get_n_methods((GIInterfaceInfo *) iface_info);
+
+    for (i = 0; i < length; i++) {
+        GIFunctionInfo *method = g_interface_info_get_method((GIInterfaceInfo *) iface_info, i);
+        const gchar *method_name = g_base_info_get_name((GIBaseInfo *) method);
+        gchar pymethod_name[250];
+        PyObject *py_method;
+        void *method_ptr = iface + i * sizeof(void*);
+
+        printf("%s\n", method_name);
+
+        g_snprintf(pymethod_name, sizeof(pymethod_name), "do_%s", pymethod_name);
+        py_method = PyObject_GetAttrString((PyObject *) pytype, pymethod_name);
+        if (py_method && !PyObject_TypeCheck(py_method, &PyCFunction_Type)) {
+            method_ptr = interface_method;
+        } else {
+            PyErr_Clear();
+            if (parent_iface) {
+                method_ptr = parent_iface + i * sizeof(void*);
+            }
+            Py_XDECREF(py_method);
+        }
+
+        g_base_info_unref((GIBaseInfo *) method);
+    }
+    */
+}
+
+static PyObject *
+_wrap_g_interface_info_register(PyGIBaseInfo *self)
+{
+    GType gtype;
+    GInterfaceInfo *info_struct = g_new0(GInterfaceInfo, 1);
+
+    info_struct->interface_init = (GInterfaceInitFunc) initialize_interface;
+    info_struct->interface_finalize = NULL;
+    info_struct->interface_data = NULL;
+
+    gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *) self->info);
+    pyg_register_interface_info(gtype, info_struct);
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef _PyGIInterfaceInfo_methods[] = {
+    { "getMethods", (PyCFunction)_wrap_g_interface_info_get_methods, METH_NOARGS },
+    { "register", (PyCFunction)_wrap_g_interface_info_register, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+
+/* GIConstantInfo */
+NEW_CLASS("ConstantInfo", GIConstantInfo);
+
+static PyMethodDef _PyGIConstantInfo_methods[] = {
+    { NULL, NULL, 0 }
+};
+
+
+/* GIValueInfo */
+NEW_CLASS("ValueInfo", GIValueInfo);
+
+static PyObject *
+_wrap_g_value_info_get_value(PyGIBaseInfo *self)
+{
+    glong value;
+
+    g_base_info_ref(self->info);
+    value = g_value_info_get_value((GIValueInfo*)self->info);
+    g_base_info_unref(self->info);
+
+    return PyLong_FromLong(value);
+}
+
+
+static PyMethodDef _PyGIValueInfo_methods[] = {
+    { "getValue", (PyCFunction)_wrap_g_value_info_get_value, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+
+/* GISignalInfo */
+NEW_CLASS("SignalInfo", GISignalInfo);
+
+static PyMethodDef _PyGISignalInfo_methods[] = {
+    { NULL, NULL, 0 }
+};
+
+
+/* GIVFuncInfo */
+NEW_CLASS("VFuncInfo", GIVFuncInfo);
+
+static PyMethodDef _PyGIVFuncInfo_methods[] = {
+    { NULL, NULL, 0 }
+};
+
+/* GIPropertyInfo */
+NEW_CLASS("PropertyInfo", GIPropertyInfo);
+
+static PyMethodDef _PyGIPropertyInfo_methods[] = {
+    { NULL, NULL, 0 }
+};
+
+/* GIFieldInfo */
+NEW_CLASS("FieldInfo", GIFieldInfo);
+
+static PyObject *
+_wrap_g_field_info_get_value(PyGIBaseInfo *self, PyObject *args)
+{
+    PyObject *obj;
+    void *buffer;
+    GArgument value;
+    GIFieldInfo *field_info;
+    PyObject *retval;
+
+    field_info = (GIFieldInfo *)self->info;
+
+    if (!PyArg_ParseTuple(args, "O:TypeInfo.getValue", &obj))
+        return NULL;
+
+    GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) self->info);
+    GIInfoType container_type = g_base_info_get_type(container);
+
+    if (container_type == GI_INFO_TYPE_STRUCT || container_type == GI_INFO_TYPE_BOXED) {
+        PyObject *pybuffer = PyObject_GetAttrString(obj, "__buffer__");
+        PyBufferProcs *buffer_procs = pybuffer->ob_type->tp_as_buffer;
+        if (buffer_procs == NULL || buffer_procs->bf_getreadbuffer == 0) {
+            PyErr_SetString(PyExc_RuntimeError, "Failed to get buffer for struct");
+            return NULL;
+        }
+        (*buffer_procs->bf_getreadbuffer)(pybuffer, 0, &buffer);
+    } else {
+        buffer = ((PyGObject *) obj)->obj;
+        printf("obj: %p\n", buffer);
+    }
+
+    if (!g_field_info_get_field (field_info, buffer, &value)) {
+        PyErr_SetString(PyExc_RuntimeError, "Failed to get value for field");
+        return NULL;
+    }
+
+    retval = pyg_argument_to_pyobject (&value, g_field_info_get_type (field_info));
+    if (retval == NULL) {
+        return NULL;
+    }
+
+    Py_INCREF(retval);
+    return retval;
+}
+
+static PyObject *
+_wrap_g_field_info_set_value(PyGIBaseInfo *self, PyObject *args)
+{
+    PyObject *obj;
+    void *buffer;
+    GArgument arg;
+    GIFieldInfo *field_info;
+    PyObject *value;
+
+    field_info = (GIFieldInfo *)self->info;
+
+    if (!PyArg_ParseTuple(args, "OO:TypeInfo.setValue", &obj, &value))
+        return NULL;
+
+    GIBaseInfo *container = g_base_info_get_container((GIBaseInfo *) self->info);
+    GIInfoType container_type = g_base_info_get_type(container);
+
+    if (container_type == GI_INFO_TYPE_STRUCT || container_type == GI_INFO_TYPE_BOXED) {
+        PyObject *pybuffer = PyObject_GetAttrString(obj, "__buffer__");
+        PyBufferProcs *buffer_procs = pybuffer->ob_type->tp_as_buffer;
+        if (buffer_procs == NULL || buffer_procs->bf_getreadbuffer == 0) {
+            PyErr_SetString(PyExc_RuntimeError, "Failed to get buffer for struct");
+            return NULL;
+        }
+        (*buffer_procs->bf_getreadbuffer)(pybuffer, 0, &buffer);
+    } else {
+        buffer = ((PyGObject *) obj)->obj;
+    }
+
+    arg = pyg_argument_from_pyobject(value, g_field_info_get_type (field_info));
+
+    if (!g_field_info_set_field (field_info, buffer, &arg)) {
+        PyErr_SetString(PyExc_RuntimeError, "Failed to set value for field");
+        return NULL;
+    }
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef _PyGIFieldInfo_methods[] = {
+    { "getValue", (PyCFunction)_wrap_g_field_info_get_value, METH_VARARGS },
+    { "setValue", (PyCFunction)_wrap_g_field_info_set_value, METH_VARARGS },
+    { NULL, NULL, 0 }
+};
+
+/* ArgInfo */
+NEW_CLASS("ArgInfo", GIArgInfo);
+
+static PyObject *
+_wrap_g_arg_info_get_type(PyGIBaseInfo *self)
+{
+    return pyg_info_new(g_arg_info_get_type((GIArgInfo*)self->info));
+}
+
+static PyObject *
+_wrap_g_arg_info_get_direction(PyGIBaseInfo *self)
+{
+    return PyInt_FromLong(g_arg_info_get_direction((GIArgInfo*)self->info));
+}
+
+static PyMethodDef _PyGIArgInfo_methods[] = {
+    { "getType", (PyCFunction)_wrap_g_arg_info_get_type, METH_NOARGS },
+    { "getDirection", (PyCFunction)_wrap_g_arg_info_get_direction, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+/* TypeInfo */
+NEW_CLASS("TypeInfo", GITypeInfo);
+
+static PyObject *
+_wrap_g_type_info_get_tag(PyGIBaseInfo *self)
+{
+    return PyInt_FromLong(g_type_info_get_tag((GITypeInfo*)self->info));
+}
+
+static PyObject *
+_wrap_g_type_info_get_param_type(PyGIBaseInfo *self, PyObject *args)
+{
+    int index;
+
+    if (!PyArg_ParseTuple(args, "i:TypeInfo.getParamType",
+                          &index))
+        return NULL;
+
+    return pyg_info_new(g_type_info_get_param_type((GITypeInfo*)self->info, index));
+}
+
+static PyObject *
+_wrap_g_type_info_get_interface(PyGIBaseInfo *self)
+{
+    return pyg_info_new(g_type_info_get_interface((GITypeInfo*)self->info));
+}
+
+static PyMethodDef _PyGITypeInfo_methods[] = {
+    { "getTag", (PyCFunction)_wrap_g_type_info_get_tag, METH_NOARGS },
+    { "getParamType", (PyCFunction)_wrap_g_type_info_get_param_type, METH_VARARGS },
+    { "getInterface", (PyCFunction)_wrap_g_type_info_get_interface, METH_NOARGS },
+    { NULL, NULL, 0 }
+};
+
+#if 0
+GIErrorDomainInfo
+#endif
+
+/* GIUnresolvedInfo */
+NEW_CLASS("UnresolvedInfo", GIUnresolvedInfo);
+
+static PyMethodDef _PyGIUnresolvedInfo_methods[] = {
+    { NULL, NULL, 0 }
+};
+
+
diff --git a/girepository/bank-repository.c b/girepository/bank-repository.c
new file mode 100644
index 0000000..699806c
--- /dev/null
+++ b/girepository/bank-repository.c
@@ -0,0 +1,237 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 sw=4 noet ai cindent :
+ * 
+ * Copyright (C) 2005  Johan Dahlin <johan gnome org>
+ *
+ * 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 "bank.h"
+
+static PyMethodDef _PyGIRepository_methods[];
+
+PyTypeObject PyGIRepository_Type = {
+    PyObject_HEAD_INIT(NULL)
+    0,			
+    "bank.IRepository",	
+    sizeof(PyGIRepository),	
+    0,			
+    /* methods */
+    (destructor)0,	
+    (printfunc)0,	
+    (getattrfunc)0,	
+    (setattrfunc)0,	
+    (cmpfunc)0,
+    (reprfunc)0,	
+    0,			
+    0,		
+    0,		
+    (hashfunc)0,		
+    (ternaryfunc)0,		
+    (reprfunc)0,		
+    (getattrofunc)0,		
+    (setattrofunc)0,		
+    0,				
+    Py_TPFLAGS_DEFAULT, 
+    NULL,
+    (traverseproc)0,		
+    (inquiry)0,
+    (richcmpfunc)0,	
+    0,
+    (getiterfunc)0,
+    (iternextfunc)0,
+    _PyGIRepository_methods,
+    0,				
+    0,		       	
+    NULL,		
+    NULL,		
+    (descrgetfunc)0,	
+    (descrsetfunc)0,	
+    0,                 
+    (initproc)0,
+};
+
+static PyObject *
+_wrap_g_irepository_require(PyGIRepository *self,
+			    PyObject *args,
+			    PyObject *kwargs)
+{
+    static char *kwlist[] = { "namespace", "lazy", NULL };
+    gchar *namespace;
+    PyObject *lazy_obj = NULL;
+    int flags = 0;
+    GTypelib *ret;
+    PyObject *pyret;
+    GError *error = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+				     "s|O:GIRepository.require",
+				     kwlist, &namespace, &lazy_obj))
+        return NULL;
+
+    if (lazy_obj != NULL && PyObject_IsTrue(lazy_obj))
+	flags |= G_IREPOSITORY_LOAD_FLAG_LAZY;
+
+    /* TODO - handle versioning in some way, need to figure out what
+     * this looks like Python side. 
+     */
+    ret = g_irepository_require(self->repo, namespace, NULL, flags, &error);
+
+    if (ret == NULL) {
+#if 0
+	g_print ("ERROR: %s (FIXME: raise GError exception)\n",
+		 error->message);
+	g_clear_error (&error);
+#endif
+	Py_INCREF(Py_None);
+	return Py_None;
+    }
+    pyret = PyBool_FromLong(ret != NULL);
+    Py_INCREF(pyret);
+    return pyret;
+}
+
+static PyObject *
+_wrap_g_irepository_find_by_name(PyGIRepository *self,
+				 PyObject *args,
+				 PyObject *kwargs)
+{
+    static char *kwlist[] = { "namespace", "name", NULL };
+    char *namespace, *name;
+    GIBaseInfo *info;
+    
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+				     "ss:GIRepository.findByName",
+				     kwlist, &namespace, &name))
+        return NULL;
+
+    info = g_irepository_find_by_name (self->repo, namespace, name);
+    if (!info) {
+	Py_INCREF(Py_None);
+	return Py_None;
+    }
+    
+    return pyg_info_new(info);
+}
+
+static PyObject *
+_wrap_g_irepository_get_namespaces(PyGIRepository *self)
+{
+    char ** namespaces;
+    int i, length;
+    PyObject *retval;
+    
+    namespaces = g_irepository_get_loaded_namespaces(self->repo);
+
+    length = g_strv_length(namespaces);
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++)
+	PyTuple_SetItem(retval, i, PyString_FromString(namespaces[i]));
+
+    g_strfreev (namespaces);
+
+    return retval;
+}
+
+static PyObject *
+_wrap_g_irepository_get_infos(PyGIRepository *self,
+			      PyObject *args,
+			      PyObject *kwargs)
+{
+    static char *kwlist[] = { "namespace", NULL };
+    char *namespace;
+    int i, length;
+    PyObject *retval;
+    
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+				     "s:GIRepository.getInfos",
+				     kwlist, &namespace))
+        return NULL;
+
+    length = g_irepository_get_n_infos(self->repo, namespace);
+
+    retval = PyTuple_New(length);
+
+    for (i = 0; i < length; i++) {
+	GIBaseInfo *info = g_irepository_get_info(self->repo, namespace, i);
+	PyTuple_SetItem(retval, i, pyg_info_new(info));
+    }
+
+    return retval;
+}
+
+static PyObject *
+_wrap_g_irepository_is_registered(PyGIRepository *self,
+				  PyObject *args,
+				  PyObject *kwargs)
+{
+    static char *kwlist[] = { "namespace", NULL };
+    char *namespace;
+ 
+    
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+				     "s:GIRepository.isRegistered",
+				     kwlist, &namespace))
+        return NULL;
+
+    return PyBool_FromLong(g_irepository_is_registered(self->repo, namespace, NULL));
+}
+
+static PyObject *
+_wrap_g_irepository_get_c_prefix(PyGIRepository *self,
+				 PyObject *args,
+				 PyObject *kwargs)
+{
+    static char *kwlist[] = { "namespace", NULL };
+    char *namespace;
+
+
+    if (!PyArg_ParseTupleAndKeywords(args, kwargs,
+				     "s:GIRepository.getCPrefix",
+				     kwlist, &namespace))
+        return NULL;
+
+    return PyString_FromString(g_irepository_get_c_prefix(self->repo, namespace));
+}
+
+static PyObject *
+_wrap_g_irepository_get_default(PyObject *_)
+{
+    static PyGIRepository *self = NULL;
+
+    if (!self) {
+        self = (PyGIRepository *)PyObject_New(PyGIRepository,
+					      &PyGIRepository_Type);
+	if (self == NULL)
+	    return NULL;
+
+	self->repo = g_irepository_get_default();
+    }
+
+    return (PyObject*)self;
+}
+
+static PyMethodDef _PyGIRepository_methods[] = {
+    { "require", (PyCFunction)_wrap_g_irepository_require, METH_VARARGS|METH_KEYWORDS },
+    { "getNamespaces", (PyCFunction)_wrap_g_irepository_get_namespaces, METH_NOARGS },
+    { "getInfos", (PyCFunction)_wrap_g_irepository_get_infos, METH_VARARGS|METH_KEYWORDS },
+    { "getDefault", (PyCFunction)_wrap_g_irepository_get_default, METH_STATIC|METH_NOARGS },
+    { "findByName", (PyCFunction)_wrap_g_irepository_find_by_name, METH_VARARGS|METH_KEYWORDS },
+    { "isRegistered", (PyCFunction)_wrap_g_irepository_is_registered, METH_VARARGS|METH_KEYWORDS },
+    { "getCPrefix", (PyCFunction)_wrap_g_irepository_get_c_prefix, METH_VARARGS|METH_KEYWORDS },
+    { NULL, NULL, 0 }
+};
+
diff --git a/girepository/bank.c b/girepository/bank.c
new file mode 100644
index 0000000..c069a18
--- /dev/null
+++ b/girepository/bank.c
@@ -0,0 +1,155 @@
+/* -*- Mode: C; c-basic-offset: 4 -*-
+ * vim: set ts=8 sts=4 sw=4 noet ai cindent :
+ *
+ * Copyright (C) 2005  Johan Dahlin <johan gnome org>
+ *
+ * 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 "bank.h"
+#include <pygobject.h>
+
+#define REGISTER_TYPE(d, type, name) \
+    type.ob_type = &PyType_Type; \
+    type.tp_alloc = PyType_GenericAlloc; \
+    type.tp_new = PyType_GenericNew; \
+    if (PyType_Ready(&type)) \
+        return; \
+    PyDict_SetItemString(d, name, (PyObject *)&type); \
+    Py_INCREF(&type);
+
+#define REGISTER_SUBTYPE(d, type, name, base) \
+    type.tp_base = &base;                     \
+    REGISTER_TYPE(d, type, name)
+
+static PyObject *
+_wrap_set_object_has_new_constructor(PyGIBaseInfo *self, PyObject *args)
+{
+    PyObject *pygtype;
+
+    if (!PyArg_ParseTuple(args, "O:setObjectHasNewConstructor", &pygtype))
+        return NULL;
+
+    pyg_set_object_has_new_constructor(pyg_type_from_object(pygtype));
+
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+static PyMethodDef pybank_functions[] = {
+    { "setObjectHasNewConstructor", (PyCFunction)_wrap_set_object_has_new_constructor, METH_VARARGS },
+    { NULL, NULL, 0 }
+};
+
+static void
+register_types(PyObject *d)
+{
+    REGISTER_TYPE(d, PyGIRepository_Type, "Repository");
+    REGISTER_TYPE(d, PyGIBaseInfo_Type, "BaseInfo");
+    REGISTER_SUBTYPE(d, PyGIUnresolvedInfo_Type,
+                     "UnresolvedInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGICallableInfo_Type,
+                     "CallableInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIFunctionInfo_Type,
+                     "FunctionInfo", PyGICallableInfo_Type);
+    REGISTER_SUBTYPE(d, PyGICallbackInfo_Type,
+                     "CallbackInfo", PyGICallableInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIRegisteredTypeInfo_Type,
+                     "RegisteredTypeInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIStructInfo_Type,
+                     "StructInfo", PyGIRegisteredTypeInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIEnumInfo_Type,
+                     "EnumInfo", PyGIRegisteredTypeInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIObjectInfo_Type,
+                     "ObjectInfo", PyGIRegisteredTypeInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIBoxedInfo_Type,
+                     "BoxedInfo", PyGIRegisteredTypeInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIInterfaceInfo_Type,
+                     "InterfaceInfo", PyGIRegisteredTypeInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIConstantInfo_Type,
+                     "ConstantInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIValueInfo_Type,
+                     "ValueInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGISignalInfo_Type,
+                     "SignalInfo", PyGICallableInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIVFuncInfo_Type,
+                     "VFuncInfo", PyGICallableInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIPropertyInfo_Type,
+                     "PropertyInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIFieldInfo_Type,
+                     "FieldInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIArgInfo_Type,
+                     "ArgInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGITypeInfo_Type,
+                     "TypeInfo", PyGIBaseInfo_Type);
+    REGISTER_SUBTYPE(d, PyGIUnionInfo_Type,
+                     "UnionInfo", PyGIRegisteredTypeInfo_Type);
+}
+
+static void
+register_constants(PyObject *m)
+{
+    PyModule_AddIntConstant(m, "TYPE_TAG_VOID", GI_TYPE_TAG_VOID);
+    PyModule_AddIntConstant(m, "TYPE_TAG_BOOLEAN", GI_TYPE_TAG_BOOLEAN);
+    PyModule_AddIntConstant(m, "TYPE_TAG_INT8", GI_TYPE_TAG_INT8);
+    PyModule_AddIntConstant(m, "TYPE_TAG_UINT8", GI_TYPE_TAG_UINT8);
+    PyModule_AddIntConstant(m, "TYPE_TAG_INT16", GI_TYPE_TAG_INT16);
+    PyModule_AddIntConstant(m, "TYPE_TAG_UINT16", GI_TYPE_TAG_UINT16);
+    PyModule_AddIntConstant(m, "TYPE_TAG_INT32", GI_TYPE_TAG_INT32);
+    PyModule_AddIntConstant(m, "TYPE_TAG_UINT32", GI_TYPE_TAG_UINT32);
+    PyModule_AddIntConstant(m, "TYPE_TAG_INT64", GI_TYPE_TAG_INT64);
+    PyModule_AddIntConstant(m, "TYPE_TAG_UINT64", GI_TYPE_TAG_UINT64);
+    /* FIXME: Removed from metadata format, fix properly by introducing
+       special-case struct */
+/*     PyModule_AddIntConstant(m, "TYPE_TAG_GSTRING", GI_TYPE_TAG_GSTRING); */
+    PyModule_AddIntConstant(m, "TYPE_TAG_INT", GI_TYPE_TAG_INT);
+    PyModule_AddIntConstant(m, "TYPE_TAG_UINT", GI_TYPE_TAG_UINT);
+    PyModule_AddIntConstant(m, "TYPE_TAG_LONG", GI_TYPE_TAG_LONG);
+    PyModule_AddIntConstant(m, "TYPE_TAG_ULONG", GI_TYPE_TAG_ULONG);
+    PyModule_AddIntConstant(m, "TYPE_TAG_SSIZE", GI_TYPE_TAG_SSIZE);
+    PyModule_AddIntConstant(m, "TYPE_TAG_SIZE", GI_TYPE_TAG_SIZE);
+    PyModule_AddIntConstant(m, "TYPE_TAG_FLOAT", GI_TYPE_TAG_FLOAT);
+    PyModule_AddIntConstant(m, "TYPE_TAG_DOUBLE", GI_TYPE_TAG_DOUBLE);
+    PyModule_AddIntConstant(m, "TYPE_TAG_TIME_T", GI_TYPE_TAG_TIME_T);
+    PyModule_AddIntConstant(m, "TYPE_TAG_GTYPE", GI_TYPE_TAG_GTYPE);
+    PyModule_AddIntConstant(m, "TYPE_TAG_UTF8", GI_TYPE_TAG_UTF8);
+    PyModule_AddIntConstant(m, "TYPE_TAG_FILENAME", GI_TYPE_TAG_FILENAME);
+    PyModule_AddIntConstant(m, "TYPE_TAG_ARRAY", GI_TYPE_TAG_ARRAY);
+    PyModule_AddIntConstant(m, "TYPE_TAG_INTERFACE", GI_TYPE_TAG_INTERFACE);
+    PyModule_AddIntConstant(m, "TYPE_TAG_GLIST", GI_TYPE_TAG_GLIST);
+    PyModule_AddIntConstant(m, "TYPE_TAG_GSLIST", GI_TYPE_TAG_GSLIST);
+    PyModule_AddIntConstant(m, "TYPE_TAG_GHASH", GI_TYPE_TAG_GHASH);
+    PyModule_AddIntConstant(m, "TYPE_TAG_ERROR", GI_TYPE_TAG_ERROR);
+
+    PyModule_AddIntConstant(m, "DIRECTION_IN", GI_DIRECTION_IN);
+    PyModule_AddIntConstant(m, "DIRECTION_OUT", GI_DIRECTION_OUT);
+    PyModule_AddIntConstant(m, "DIRECTION_INOUT", GI_DIRECTION_INOUT);
+}
+
+void
+initrepo(void)
+{
+    PyObject *d, *m;
+
+    m = Py_InitModule("girepository.repo", pybank_functions);
+    d = PyModule_GetDict(m);
+
+    g_type_init();
+
+    pygobject_init(-1, -1, -1);
+    register_types(d);
+    register_constants(m);
+}
+
diff --git a/girepository/bank.h b/girepository/bank.h
new file mode 100644
index 0000000..d960483
--- /dev/null
+++ b/girepository/bank.h
@@ -0,0 +1,80 @@
+/* -*- Mode: C; c-basic-offset: 4 -*- */
+/* 
+ * Copyright (C) 2005  Johan Dahlin <johan gnome org>
+ *
+ * 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 <Python.h>
+#include <girepository.h>
+
+/* This was added in Python 2.4 */
+#ifndef Py_CLEAR
+#define Py_CLEAR(op)                            \
+        do {                                    \
+                if (op) {                       \
+                        PyObject *tmp = (PyObject *)(op);       \
+                        (op) = NULL;            \
+                        Py_DECREF(tmp);         \
+                }                               \
+        } while (0)
+#endif /* Py_CLEAR */
+
+typedef struct {
+    PyObject_HEAD
+    GIRepository *repo;
+} PyGIRepository;
+
+extern PyTypeObject PyGIRepository_Type;
+
+PyObject * pyg_info_new(gpointer info);
+
+typedef struct {
+    PyObject_HEAD
+    GIBaseInfo *info;
+    PyObject *instance_dict;
+    PyObject *weakreflist;
+} PyGIBaseInfo;
+
+extern PyTypeObject PyGIBaseInfo_Type;
+extern PyTypeObject PyGICallableInfo_Type;
+extern PyTypeObject PyGIFunctionInfo_Type;
+extern PyTypeObject PyGICallbackInfo_Type;
+extern PyTypeObject PyGIRegisteredTypeInfo_Type;
+extern PyTypeObject PyGIStructInfo_Type;
+extern PyTypeObject PyGIUnionInfo_Type;
+extern PyTypeObject PyGIEnumInfo_Type;
+extern PyTypeObject PyGIObjectInfo_Type;
+extern PyTypeObject PyGIBoxedInfo_Type;
+extern PyTypeObject PyGIInterfaceInfo_Type;
+extern PyTypeObject PyGIConstantInfo_Type;
+extern PyTypeObject PyGIValueInfo_Type;
+extern PyTypeObject PyGISignalInfo_Type;
+extern PyTypeObject PyGIVFuncInfo_Type;
+extern PyTypeObject PyGIPropertyInfo_Type;
+extern PyTypeObject PyGIFieldInfo_Type;
+extern PyTypeObject PyGIArgInfo_Type;
+extern PyTypeObject PyGITypeInfo_Type;
+#if 0
+extern PyTypeObject PyGIErrorDomainInfo_Type;
+#endif
+extern PyTypeObject PyGIUnresolvedInfo_Type;
+
+GArgument pyg_argument_from_pyobject(PyObject *object,
+				     GITypeInfo *info);
+PyObject*  pyg_argument_to_pyobject(GArgument *arg,
+				    GITypeInfo *info);
+PyObject*  pyarray_to_pyobject(gpointer array, int length, GITypeInfo *info);
+
diff --git a/girepository/btypes.py b/girepository/btypes.py
new file mode 100644
index 0000000..03e8826
--- /dev/null
+++ b/girepository/btypes.py
@@ -0,0 +1,300 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+#
+# Copyright (C) 2005, 2007  Johan Dahlin <johan gnome org>
+#
+# 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
+#
+
+import gobject
+
+import new
+
+from . import repo
+
+from .repository import repository
+
+class Callable(object):
+    
+    # Types of callables
+    INSTANCE_METHOD = 'method'
+    STATIC_METHOD = 'static'
+    CLASS_METHOD = 'class'
+    FUNTION = 'function'
+
+    def __init__(self, info):
+        self.info = info
+        self.call_type = None
+
+    def type_check(self, name, value, argType):
+        tag = argType.getTag()
+        if tag == repo.TYPE_TAG_UTF8:
+            if not isinstance(value, basestring) and value is not None:
+                raise TypeError("%s must be string, not %s" % (
+                        name, type(value).__name__))
+        elif tag in (repo.TYPE_TAG_INT,
+                     repo.TYPE_TAG_INT8,
+                     repo.TYPE_TAG_UINT,
+                     repo.TYPE_TAG_UINT8,
+                     repo.TYPE_TAG_INT16,
+                     repo.TYPE_TAG_UINT16,
+                     repo.TYPE_TAG_INT32):
+            try:
+                int(value)
+            except ValueError:
+                raise TypeError("%s must be int, not %s" % (name, type(value).__name__))
+            if tag in (repo.TYPE_TAG_UINT,
+                       repo.TYPE_TAG_UINT8,
+                       repo.TYPE_TAG_UINT16) and value < 0:
+                raise TypeError("%s must be an unsigned value, not %s", name, value)
+        elif tag in (repo.TYPE_TAG_UINT32,
+                     repo.TYPE_TAG_INT64,
+                     repo.TYPE_TAG_UINT64,
+                     repo.TYPE_TAG_ULONG):
+            try:
+                long(value)
+            except ValueError:
+                raise TypeError("%s must be int or long, not %s" % (name, type(value).__name__))
+            if tag in (repo.TYPE_TAG_UINT32,
+                       repo.TYPE_TAG_UINT64,
+                       repo.TYPE_TAG_ULONG) and value < 0:
+                raise TypeError("%s must be an unsigned value, not %s", name, value)
+        elif tag in (repo.TYPE_TAG_FLOAT,
+                     repo.TYPE_TAG_DOUBLE):
+            try:
+                float(value)
+            except ValueError:
+                raise TypeError("%s must be float, not %s" % (name, type(value).__name__))
+        elif tag == repo.TYPE_TAG_INTERFACE:
+            # TODO
+            pass
+        elif tag == repo.TYPE_TAG_BOOLEAN:
+            try:
+                bool(value)
+            except ValueError:
+                raise TypeError("%s must be bool, not %s" % (name, type(value).__name__))
+        elif tag == repo.TYPE_TAG_ARRAY:
+            if value is not None:
+                raise TypeError("Must pass None for arrays currently")
+        elif tag == repo.TYPE_TAG_ERROR:
+            # TODO
+            pass
+        elif tag == repo.TYPE_TAG_VOID:
+            # TODO
+            pass
+        else:
+            raise NotImplementedError('type checking for tag %d' % tag)
+
+    def __call__(self, *args, **kwargs):
+        infoArgs = list(self.info.getArgs())
+        requiredArgs = 0
+        for arg in infoArgs:
+            direct = arg.getDirection()
+            if direct in [repo.DIRECTION_IN, repo.DIRECTION_INOUT]:
+                requiredArgs += 1
+
+        is_method = self.call_type in [self.INSTANCE_METHOD, self.CLASS_METHOD]
+        if is_method:
+            requiredArgs += 1
+
+        # TODO: put the kwargs in their right positions
+        totalInArgs = args + tuple(kwargs.values())
+
+        if len(totalInArgs) != requiredArgs:
+            raise TypeError('%r requires %d arguments, passed %d instead.' % (
+                self, requiredArgs, len(totalInArgs)))
+
+        for i, value in enumerate(totalInArgs):
+            if not is_method or i > 0:
+                off = is_method and 1 or 0
+                infoArg = infoArgs[i - off]
+                argType = infoArg.getType()
+                name = infoArg.getName()
+                self.type_check(name, value, argType)
+
+        retval = self.info.invoke(*totalInArgs)
+
+        if self.info.isConstructor():
+            return None
+
+        return retval
+
+class Function(Callable):
+    def __init__(self, info):
+        Callable.__init__(self, info)
+        self.info = info
+        self.static = True
+
+    def __repr__(self):
+        return "<function %s>" % (self.info.getName(),)
+
+
+class Method(Callable):
+    
+    def __init__(self, info, className, call_type=Callable.INSTANCE_METHOD):
+        Callable.__init__(self, info)
+        self.object = None
+        self.className = className
+        self.call_type = call_type
+        self.__name__ = info.getName()
+        self.__module__ = info.getNamespace()
+
+    def newType(self, retval, type_info=None):
+        if type_info == None:
+            type_info = self.info.getReturnType()
+
+        info = type_info.getInterface()
+        klass = getClass(info)
+        obj = klass.__new__(klass)
+        obj._object = retval
+        return obj
+
+    #def __get__(self, instance, type):
+        #if instance is None:
+            #return self
+
+        #def wrapper(*args, **kwargs):
+            #return self(instance, *args, **kwargs)
+
+        #return wrapper
+
+    def __repr__(self):
+        return "<method %s of %s.%s object>" % (
+            self.__name__,
+            self.__module__,
+            self.className)
+
+class FieldDescriptor(object):
+    def __init__(self, info):
+        self._info = info
+
+    def __get__(self, obj, klass=None):
+        return self._info.getValue(obj)
+
+    def __set__(self, obj, value):
+        return self._info.setValue(obj, value)
+
+class PyBankMeta(gobject.GObjectMeta):
+    def __init__(cls, name, bases, dict_):
+        gobject.GObjectMeta.__init__(cls, name, bases, dict_)
+
+        if hasattr(cls, '__gtype__'):
+            repo.setObjectHasNewConstructor(cls.__gtype__)
+
+        # Only set up the wrapper methods and fields in their base classes
+        if name == cls.__info__.getName():
+            needs_constructor = not '__init__' in dict_
+            cls._setup_methods(needs_constructor)
+
+            if hasattr(cls.__info__, 'getFields'):
+                cls._setup_fields()
+
+    def _setup_methods(cls, needs_constructor):
+        info = cls.__info__
+        constructors = []
+        static_methods = []
+        for method in info.getMethods():
+            name = method.getName()
+
+            if method.isConstructor():
+                constructors.append(method)
+            elif method.isMethod():
+                func = Method(method, cls.__name__)
+                setattr(cls, name, new.instancemethod(func, None, cls))
+            else:
+                static_methods.append(method)
+
+        if hasattr(info, 'getInterfaces'):
+            for interface in info.getInterfaces():
+                for method in interface.getMethods():
+                    name = method.getName()
+                    if method.isMethod():
+                        func = Method(method, interface.getName())
+                        setattr(cls, name, new.instancemethod(func, None, cls))
+                    else:
+                        static_methods.append(method)
+
+        winner = None
+        if needs_constructor:
+            if len(constructors) == 1:
+                winner = constructors[0]
+            else:
+                for constructor in constructors:
+                    if constructor.getName() == 'new':
+                        winner = constructor
+                        break
+
+        if winner is not None:
+            func = Method(winner, cls.__name__, call_type=Method.CLASS_METHOD)
+            func.__name__ = '__init__'
+            func.__orig_name__ = winner.getName()
+            cls.__init__ = new.instancemethod(func, None, cls)
+            # TODO: do we want the constructor as a static method?
+            #constructors.remove(winner)
+
+        static_methods.extend(constructors)
+        for static_method in static_methods:
+            func = Method(static_method, cls.__name__, call_type=Method.STATIC_METHOD)
+            setattr(cls, static_method.getName(), staticmethod(func))
+
+    def _setup_fields(cls):
+        info = cls.__info__
+        for field in info.getFields():
+            name = field.getName().replace('-', '_')
+            setattr(cls, name, FieldDescriptor(field))
+
+_classDict = {}
+
+def getClass(info):
+    className = info.getName()
+    namespaceName = info.getNamespace()
+    fullName = namespaceName + '.' + className
+
+    klass = _classDict.get(fullName)
+    if klass is None:
+        module = repository.get_module(info.getNamespace())
+        klass = getattr(module, className)
+    return klass
+
+def buildType(info, bases):
+    className = info.getName()
+    namespaceName = info.getNamespace()
+    fullName = namespaceName + '.' + className
+
+    if _classDict.has_key(fullName):
+        return _classDict[fullName]
+
+    namespace = {}
+    namespace['__info__'] = info
+    namespace['__module__'] = namespaceName
+    newType = PyBankMeta(className, bases, namespace)
+
+    _classDict[fullName] = newType
+    
+    return newType
+
+class BaseBlob(object):
+    """Base class for Struct, Boxed and Union.
+    """
+    def __init__(self, buf=None):
+        if buf is None:
+            buf = self.__info__.newBuffer()
+        self.__buffer__ = buf
+
+    def __eq__(self, other):
+        for field in self.__info__.getFields():
+            if getattr(self, field.getName()) != getattr(other, field.getName()):
+                return False
+        return True
+
diff --git a/girepository/importer.py b/girepository/importer.py
new file mode 100644
index 0000000..c371f79
--- /dev/null
+++ b/girepository/importer.py
@@ -0,0 +1,52 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+#
+# Copyright (C) 2005,2007 Johan Dahlin <johan gnome org>
+#
+# 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
+#
+
+import os
+import sys
+
+from .repository import repository
+
+class DynamicImporter(object):
+    def __init__(self, name, path):
+        self.name = name
+        self.path = path
+
+    @staticmethod
+    def find_module(name, path=None):
+        if name == 'cairo':
+            return None
+        namespace = repository.require(name)
+        if namespace:
+            return DynamicImporter(name, path)
+
+    def load_module(self, name):
+        from .module import DynamicModule
+        module_name = 'girepository.overrides.%s' % (name,)
+        try:
+            d = {}
+            module = __import__(module_name, d, d, ' ', 2)
+            modtype = getattr(module, name + 'Module')
+        except ImportError, e:
+            modtype = DynamicModule
+        return modtype(name, self.path)
+
+
+def install_importhook():
+    sys.meta_path.append(DynamicImporter)
+
diff --git a/girepository/module.py b/girepository/module.py
new file mode 100644
index 0000000..2a87816
--- /dev/null
+++ b/girepository/module.py
@@ -0,0 +1,224 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+#
+# Copyright (C) 2007 Johan Dahlin <johan gnome org>
+#
+# 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
+#
+
+import os
+
+import gobject
+from gobject import GEnum
+
+from .btypes import Function, BaseBlob, buildType
+from .repo import EnumInfo, FunctionInfo, ObjectInfo, UnresolvedInfo, \
+                  InterfaceInfo, StructInfo, BoxedInfo
+from .repository import repository
+
+class DynamicModule(object):
+    def __init__(self, namespace, path):
+        self._namespace = namespace
+        self._path = path
+        repository.register(self, namespace, path)
+        self.created()
+
+    @property
+    def __file__(self):
+        return self._namespace
+
+    @property
+    def __name__(self):
+        return self._namespace
+
+    @property
+    def __path__(self):
+        return [os.path.dirname(self.__file__)]
+
+    def __repr__(self):
+        return "<dyn-module %r from %r>" % (self._namespace, self._path)
+
+    def __getattr__(self, name):
+        type_info = repository.get_by_name(self._namespace, name)
+        if not type_info:
+            raise AttributeError("%r object has no attribute %r" % (
+                    self.__class__.__name__, name))
+
+        value = self._create_attribute(name, type_info)
+        self.__dict__[name] = value
+        return value
+
+    @property
+    def __members__(self):
+        r = []
+        for type_info in repository.get_infos(self._namespace):
+            if type_info is None:
+                continue
+            r.append(type_info.getName())
+        return r
+
+
+
+    # Override this in a subclass
+
+    def created(self):
+        pass
+
+    # Private API
+
+    def _create_attribute(self, attr, type_info):
+        if isinstance(type_info, ObjectInfo):
+            return self._create_object(type_info)
+        elif isinstance(type_info, EnumInfo):
+            return self._create_enum(type_info)
+        elif isinstance(type_info, FunctionInfo):
+            return self._create_function(type_info)
+        elif isinstance(type_info, InterfaceInfo):
+            return self._create_interface(type_info)
+        elif isinstance(type_info, StructInfo) or \
+                isinstance(type_info, BoxedInfo):
+            return self._create_boxed(type_info)
+        else:
+            raise NotImplementedError(type_info)
+
+    def _get_parent_for_object(self, object_info):
+        parent_info = object_info.getParent()
+        
+        if isinstance(parent_info, UnresolvedInfo):
+            namespace = parent_info.getNamespace()
+            __import__(namespace)
+            parent_info = object_info.getParent()
+
+        if not parent_info:
+            parent = object
+        else:
+            namespace = parent_info.getNamespace()
+            module = repository.get_module(namespace)
+            name = parent_info.getName()
+            try:
+                # Hack for gobject.Object
+                if module == gobject and name == 'Object':
+                    name = 'GObject'
+                parent = getattr(module, name)
+            except AttributeError:
+                return self._get_parent_for_object(parent_info)
+
+        if parent is None:
+            parent = object
+        return parent
+
+    def _create_object(self, object_info):
+        name = object_info.getName()
+
+        namespace = repository.get_c_prefix(object_info.getNamespace())
+        full_name = namespace + name
+        object_info.getGType()
+        gtype = None
+        try:
+            gtype = gobject.GType.from_name(full_name)
+        except RuntimeError:
+            pass
+        else:
+            if gtype.pytype is not None:
+                return gtype.pytype
+        # Check if the klass is already created, eg
+        # present in our namespace, this is necessary since we're
+        # not always entering here through the __getattr__ hook.
+        klass = self.__dict__.get(name)
+        if klass:
+            return klass
+
+        parent = self._get_parent_for_object(object_info)
+        klass = buildType(object_info, (parent,))
+        if gtype is not None:
+            klass.__gtype__ = gtype
+            gtype.pytype = klass
+        self.__dict__[name] = klass
+
+        return klass
+
+    def _create_enum(self, enum_info):
+        ns = dict(__name__=enum_info.getName(),
+                  __module__=enum_info.getNamespace())
+        for value in enum_info.getValues():
+            ns[value.getName().upper()] = value.getValue()
+        return type(enum_info.getName(), (GEnum,), ns)
+
+    def _create_function(self, function_info):
+        return Function(function_info)
+
+    def _create_interface(self, interface_info):
+        name = interface_info.getName()
+
+        namespace = repository.get_c_prefix(interface_info.getNamespace())
+        full_name = namespace + name
+        interface_info.getGType()
+        gtype = None
+        try:
+            gtype = gobject.GType.from_name(full_name)
+        except RuntimeError:
+            pass
+        else:
+            if gtype.pytype is not None:
+                return gtype.pytype
+        # Check if the klass is already created, eg
+        # present in our namespace, this is necessary since we're
+        # not always entering here through the __getattr__ hook.
+        klass = self.__dict__.get(name)
+        if klass:
+            return klass
+
+        bases = (gobject.GInterface,)
+        klass = buildType(interface_info, bases)
+        if gtype is not None:
+            klass.__gtype__ = gtype
+            gtype.pytype = klass
+            interface_info.register()
+        self.__dict__[name] = klass
+
+        return klass
+
+    def _create_boxed(self, boxed_info):
+        name = boxed_info.getName()
+
+        namespace = repository.get_c_prefix(boxed_info.getNamespace())
+        full_name = namespace + name
+        boxed_info.getGType()
+        gtype = None
+        try:
+            gtype = gobject.GType.from_name(full_name)
+        except RuntimeError:
+            pass
+        else:
+            if gtype.pytype is not None:
+                return gtype.pytype
+        # Check if the klass is already created, eg
+        # present in our namespace, this is necessary since we're
+        # not always entering here through the __getattr__ hook.
+        klass = self.__dict__.get(name)
+        if klass:
+            return klass
+
+        bases = (BaseBlob,)
+        if isinstance(boxed_info, BoxedInfo):
+            bases += gobject.Boxed
+
+        klass = buildType(boxed_info, bases)
+        if gtype is not None:
+            klass.__gtype__ = gtype
+            gtype.pytype = klass
+        self.__dict__[name] = klass
+
+        return klass
+
diff --git a/girepository/repository.py b/girepository/repository.py
new file mode 100644
index 0000000..a72c6a9
--- /dev/null
+++ b/girepository/repository.py
@@ -0,0 +1,51 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+#
+# Copyright (C) 2007 Johan Dahlin <johan gnome org>
+#
+# 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
+#
+
+import gobject
+
+from .repo import Repository
+
+class _Repository(object):
+    def __init__(self):
+        self._repo = Repository.getDefault()
+        self._modules = {}
+
+    def register(self, module, namespace, filename):
+        self._modules[namespace] = module
+
+    def require(self, namespace):
+        return self._repo.require(namespace)
+
+    def get_module(self, namespace):
+        return self._modules.get(namespace)
+
+    def get_by_name(self, namespace, name):
+        return self._repo.findByName(namespace, name)
+
+    def get_by_typename(self, typename):
+        raise NotImplemented
+
+    def get_infos(self, namespace):
+        return self._repo.getInfos(namespace)
+
+    def get_c_prefix(self, namespace):
+        return self._repo.getCPrefix(namespace)
+
+repository = _Repository()
+repository.register(gobject, 'GObject', None)



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]