[pygobject/pygobject-3-18] Don't emit require_version warning if namespace was loaded previously using g_irepository_require
- From: Christoph Reiter <creiter src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pygobject/pygobject-3-18] Don't emit require_version warning if namespace was loaded previously using g_irepository_require
- Date: Sun, 11 Oct 2015 12:45:24 +0000 (UTC)
commit 5da4041629f833f66b76dc7dfcf5400153d22eb4
Author: Christoph Reiter <creiter src gnome org>
Date: Sun Sep 6 05:35:03 2015 +0200
Don't emit require_version warning if namespace was loaded previously using g_irepository_require
Instead of tracking loaded dependencies ourself to hide warnings if they
were loaded by a previous import just look if the namespace was loaded
before the import. This (a) makes the implementation much simpler and
(b) also takes into account namespaces loaded outside of Python/PyGObject
using the libgirepository C API (as is common in applications using
libpeas with Python plugins)
This also introduces a new Python wrapper for g_irepository_is_registered()
to allow checking the loading state of namespaces before imports.
This fixes unnecessary require_version warnings in gedit, gnome-builder,
totem, rhythmbox etc.
https://bugzilla.gnome.org/show_bug.cgi?id=754491
gi/importer.py | 93 ++++++++++-----------------------------
gi/pygi-repository.c | 19 ++++++++
tests/test_import_machinery.py | 9 ----
tests/test_repository.py | 11 +++++
4 files changed, 54 insertions(+), 78 deletions(-)
---
diff --git a/gi/importer.py b/gi/importer.py
index 0acbc23..22c272b 100644
--- a/gi/importer.py
+++ b/gi/importer.py
@@ -39,34 +39,6 @@ repository = Repository.get_default()
modules = {}
-def _get_all_dependencies(namespace):
- """Like get_dependencies() but will recurse and get all dependencies.
- The namespace has to be loaded before this can be called.
-
- ::
-
- _get_all_dependencies('Gtk') -> ['Atk-1.0', 'GObject-2.0', ...]
- """
-
- todo = repository.get_dependencies(namespace)
- dependencies = []
-
- while todo:
- current = todo.pop()
- if current in dependencies:
- continue
- ns, version = current.split("-", 1)
- todo.extend(repository.get_dependencies(ns))
- dependencies.append(current)
-
- return dependencies
-
-
-# See _check_require_version()
-_active_imports = []
-_implicit_required = {}
-
-
@contextmanager
def _check_require_version(namespace, stacklevel):
"""A context manager which tries to give helpful warnings
@@ -80,47 +52,30 @@ def _check_require_version(namespace, stacklevel):
load_namespace_and_overrides()
"""
- global _active_imports, _implicit_required
-
- # This keeps track of the recursion level so we only check for
- # explicitly imported namespaces and not the ones imported in overrides
- _active_imports.append(namespace)
-
- try:
- yield
- except:
- raise
- else:
- # Keep track of all dependency versions forced due to this import, so
- # we don't warn for them in the future. This mirrors the import
- # behavior where importing will get an older version if a previous
- # import depended on it.
- for dependency in _get_all_dependencies(namespace):
- ns, version = dependency.split("-", 1)
- _implicit_required[ns] = version
- finally:
- _active_imports.remove(namespace)
-
- # Warn in case:
- # * this namespace was explicitly imported
- # * the version wasn't forced using require_version()
- # * the version wasn't forced implicitly by a previous import
- # * this namespace isn't part of glib (we have bigger problems if
- # versions change there)
- is_explicit_import = not _active_imports
- version_required = gi.get_required_version(namespace) is not None
- version_implicit = namespace in _implicit_required
- is_in_glib = namespace in ("GLib", "GObject", "Gio")
-
- if is_explicit_import and not version_required and \
- not version_implicit and not is_in_glib:
- version = repository.get_version(namespace)
- warnings.warn(
- "%(namespace)s was imported without specifying a version first. "
- "Use gi.require_version('%(namespace)s', '%(version)s') before "
- "import to ensure that the right version gets loaded."
- % {"namespace": namespace, "version": version},
- PyGIWarning, stacklevel=stacklevel)
+ was_loaded = repository.is_registered(namespace)
+
+ yield
+
+ if was_loaded:
+ # it was loaded before by another import which depended on this
+ # namespace or by C code like libpeas
+ return
+
+ if namespace in ("GLib", "GObject", "Gio"):
+ # part of glib (we have bigger problems if versions change there)
+ return
+
+ if gi.get_required_version(namespace) is not None:
+ # the version was forced using require_version()
+ return
+
+ version = repository.get_version(namespace)
+ warnings.warn(
+ "%(namespace)s was imported without specifying a version first. "
+ "Use gi.require_version('%(namespace)s', '%(version)s') before "
+ "import to ensure that the right version gets loaded."
+ % {"namespace": namespace, "version": version},
+ PyGIWarning, stacklevel=stacklevel)
class DynamicImporter(object):
diff --git a/gi/pygi-repository.c b/gi/pygi-repository.c
index a1f1ca6..b8a1931 100644
--- a/gi/pygi-repository.c
+++ b/gi/pygi-repository.c
@@ -108,6 +108,24 @@ _wrap_g_irepository_require (PyGIRepository *self,
}
static PyObject *
+_wrap_g_irepository_is_registered (PyGIRepository *self,
+ PyObject *args,
+ PyObject *kwargs)
+{
+ static char *kwlist[] = { "namespace", "version", NULL };
+ const char *namespace_;
+ const char *version = NULL;
+
+ if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|z:Repository.is_registered",
+ kwlist, &namespace_, &version)) {
+ return NULL;
+ }
+
+ return PyBool_FromLong (g_irepository_is_registered (self->repository,
+ namespace_, version));
+}
+
+static PyObject *
_wrap_g_irepository_find_by_name (PyGIRepository *self,
PyObject *args,
PyObject *kwargs)
@@ -311,6 +329,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
},
+ { "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 a1adab1..de9f1e9 100644
--- a/tests/test_import_machinery.py
+++ b/tests/test_import_machinery.py
@@ -118,15 +118,6 @@ class TestImporter(unittest.TestCase):
else:
self.assertTrue('introspection typelib' in exception_string)
- def test__get_all_dependencies(self):
- get_all_dependencies = gi.importer._get_all_dependencies
- deps = set(get_all_dependencies("Regress"))
-
- self.assertTrue('Gio-2.0' in deps)
- self.assertTrue('GObject-2.0' in deps)
- self.assertTrue('GLib-2.0' in deps)
- self.assertTrue('cairo-1.0' in deps)
-
def test_require_version_warning(self):
check = gi.importer._check_require_version
diff --git a/tests/test_repository.py b/tests/test_repository.py
index 8710ce7..4c83acd 100644
--- a/tests/test_repository.py
+++ b/tests/test_repository.py
@@ -63,6 +63,17 @@ class Test(unittest.TestCase):
self.assertEqual(repo.get_dependencies("GLib"), [])
self.assertEqual(repo.get_dependencies("GObject"), ["GLib-2.0"])
+ def test_repo_is_registered(self):
+ self.assertRaises(TypeError, repo.is_registered)
+ self.assertRaises(TypeError, repo.is_registered, None)
+ self.assertTrue(repo.is_registered("GIRepository"))
+ self.assertTrue(repo.is_registered("GIRepository", None))
+ self.assertTrue(isinstance(repo.is_registered("GIRepository"), bool))
+ self.assertTrue(repo.is_registered("GIRepository", "2.0"))
+ self.assertFalse(repo.is_registered("GIRepository", ""))
+ self.assertFalse(repo.is_registered("GIRepository", "99.0"))
+ self.assertFalse(repo.is_registered("GIRepository", "1.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]