[pygobject] Import dependencies when importing typelibs from gi.repository
- From: Christoph Reiter <creiter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject] Import dependencies when importing typelibs from gi.repository
- Date: Mon, 26 Oct 2015 08:41:12 +0000 (UTC)
commit dba1da9b0770c7dec1abd82303b9b4266fe2ce3f
Author: Christoph Reiter <creiter src gnome org>
Date: Sun Oct 4 10:13:35 2015 +0200
Import dependencies when importing typelibs from gi.repository
Recursively import a modules dependencies when importing from
gi.repository.
This fixes the case where a library depends on initialization
code of dependency overrides. For example libwnck expects
gdk_init to be called before using its API and gdk_init
gets called in the Gdk overrrides.
https://bugzilla.gnome.org/show_bug.cgi?id=656314
gi/importer.py | 12 +++++++++++-
gi/pygi-repository.c | 35 +++++++++++++++++++++++++++++++++++
tests/test_import_machinery.py | 13 +++++++++++++
tests/test_repository.py | 10 ++++++++++
4 files changed, 69 insertions(+), 1 deletions(-)
---
diff --git a/gi/importer.py b/gi/importer.py
index 22c272b..2c4fb9c 100644
--- a/gi/importer.py
+++ b/gi/importer.py
@@ -24,6 +24,7 @@
from __future__ import absolute_import
import sys
import warnings
+import importlib
from contextlib import contextmanager
import gi
@@ -93,7 +94,11 @@ class DynamicImporter(object):
if path != self.path:
return
- if repository.enumerate_versions(namespace):
+ # is_registered() is faster than enumerate_versions() and
+ # in the common case of a namespace getting loaded before its
+ # dependencies, is_registered() returns True for all dependencies.
+ if repository.is_registered(namespace) or \
+ repository.enumerate_versions(namespace):
return self
else:
raise ImportError('cannot import name %s, '
@@ -112,6 +117,11 @@ class DynamicImporter(object):
stacklevel = 4
with _check_require_version(namespace, stacklevel=stacklevel):
introspection_module = get_introspection_module(namespace)
+ # Import all dependencies first so their init functions
+ # (gdk_init, ..) in overrides get called.
+ # https://bugzilla.gnome.org/show_bug.cgi?id=656314
+ for dep in repository.get_immediate_dependencies(namespace):
+ importlib.import_module('gi.repository.' + dep.split("-")[0])
dynamic_module = load_overrides(introspection_module)
dynamic_module.__file__ = '<%s>' % fullname
diff --git a/gi/pygi-repository.c b/gi/pygi-repository.c
index b8a1931..16356f9 100644
--- a/gi/pygi-repository.c
+++ b/gi/pygi-repository.c
@@ -319,6 +319,40 @@ _wrap_g_irepository_get_dependencies (PyGIRepository *self,
return py_namespaces;
}
+
+static PyObject *
+_wrap_g_irepository_get_immediate_dependencies (PyGIRepository *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "namespace", NULL };
+ const char *namespace_;
+ char **namespaces;
+ PyObject *py_namespaces;
+ gssize i;
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+ "s:Repository.get_immediate_dependencies",
+ kwlist, &namespace_)) {
+ return NULL;
+ }
+
+ py_namespaces = PyList_New (0);
+ namespaces = g_irepository_get_immediate_dependencies (self->repository,
+ namespace_);
+
+ for (i = 0; namespaces[i] != NULL; i++) {
+ PyObject *py_namespace = PYGLIB_PyUnicode_FromString (namespaces[i]);
+ PyList_Append (py_namespaces, py_namespace);
+ Py_DECREF (py_namespace);
+ }
+
+ g_strfreev (namespaces);
+
+ return py_namespaces;
+}
+
+
static PyMethodDef _PyGIRepository_methods[] = {
{ "enumerate_versions", (PyCFunction) _wrap_g_irepository_enumerate_versions, METH_VARARGS |
METH_KEYWORDS },
{ "get_default", (PyCFunction) _wrap_g_irepository_get_default, METH_STATIC | METH_NOARGS },
@@ -329,6 +363,7 @@ static PyMethodDef _PyGIRepository_methods[] = {
{ "get_version", (PyCFunction) _wrap_g_irepository_get_version, METH_VARARGS | METH_KEYWORDS },
{ "get_loaded_namespaces", (PyCFunction) _wrap_g_irepository_get_loaded_namespaces, METH_NOARGS },
{ "get_dependencies", (PyCFunction) _wrap_g_irepository_get_dependencies, METH_VARARGS | METH_KEYWORDS
},
+ { "get_immediate_dependencies", (PyCFunction) _wrap_g_irepository_get_immediate_dependencies,
METH_VARARGS | METH_KEYWORDS },
{ "is_registered", (PyCFunction) _wrap_g_irepository_is_registered, METH_VARARGS | METH_KEYWORDS },
{ NULL, NULL, 0 }
};
diff --git a/tests/test_import_machinery.py b/tests/test_import_machinery.py
index de9f1e9..e1432b1 100644
--- a/tests/test_import_machinery.py
+++ b/tests/test_import_machinery.py
@@ -77,6 +77,19 @@ class TestModule(unittest.TestCase):
# Restore the previous cache
gi.module._introspection_modules = old_modules
+ def test_module_dependency_loading(self):
+ # Difficult to because this generally need to run in isolation to make
+ # sure GIMarshallingTests has not yet been loaded. But we can do this with:
+ # make check TEST_NAMES=test_import_machinery.TestModule.test_module_dependency_loading
+ if 'gi.repository.Gio' in sys.modules:
+ return
+
+ from gi.repository import GIMarshallingTests
+ GIMarshallingTests # PyFlakes
+
+ self.assertIn('gi.repository.Gio', sys.modules)
+ self.assertIn('gi.repository.GIMarshallingTests', sys.modules)
+
def test_static_binding_protection(self):
# Importing old static bindings once gi has been imported should not
# crash but instead give back a dummy module which produces RuntimeErrors
diff --git a/tests/test_repository.py b/tests/test_repository.py
index 4c83acd..f59f86b 100644
--- a/tests/test_repository.py
+++ b/tests/test_repository.py
@@ -74,6 +74,16 @@ class Test(unittest.TestCase):
self.assertFalse(repo.is_registered("GIRepository", "99.0"))
self.assertFalse(repo.is_registered("GIRepository", "1.0"))
+ def test_repo_get_immediate_dependencies(self):
+ self.assertRaises(TypeError, repo.get_immediate_dependencies)
+ self.assertEqual(repo.get_immediate_dependencies("GLib"), [])
+ self.assertEqual(
+ repo.get_immediate_dependencies("GObject"), ["GLib-2.0"])
+ self.assertEqual(
+ repo.get_immediate_dependencies(namespace="GObject"), ["GLib-2.0"])
+ self.assertEqual(
+ repo.get_immediate_dependencies("GIMarshallingTests"), ["Gio-2.0"])
+
def test_arg_info(self):
func_info = repo.find_by_name('GIMarshallingTests', 'array_fixed_out_struct')
args = func_info.get_arguments()
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]