[pygobject] Allow specifying a version when loading a typelib



commit 2082ee35e2a33f52bf1e8ec49cb4a43398e91989
Author: Tomeu Vizoso <tomeu vizoso collabora co uk>
Date:   Tue Jul 27 18:25:27 2010 +0200

    Allow specifying a version when loading a typelib
    
    * gi/importer.py: Defer loading the typelib until first usage.
    * gi/module.py: Load the typelib in IntrospectionModule().
    * gi/overrides/*.py: Adapt to API change.
    * gi/pygi-repository.c: Add wrappers for g_irepository_enumerate and
      g_irepository_get_version.

 gi/importer.py                     |   26 +++++----------
 gi/module.py                       |   58 +++++++++++++++++++++++------------
 gi/overrides/GIMarshallingTests.py |    2 +-
 gi/overrides/Gdk.py                |    2 +-
 gi/overrides/Gtk.py                |    2 +-
 gi/pygi-repository.c               |   56 ++++++++++++++++++++++++++++++++++-
 6 files changed, 105 insertions(+), 41 deletions(-)
---
diff --git a/gi/importer.py b/gi/importer.py
index 6076692..d18f334 100644
--- a/gi/importer.py
+++ b/gi/importer.py
@@ -27,7 +27,7 @@ import sys
 import gobject
 
 from ._gi import Repository, RepositoryError
-from .module import DynamicModule, DynamicGObjectModule, ModuleProxy
+from .module import DynamicModule, DynamicGObjectModule
 
 
 repository = Repository.get_default()
@@ -48,10 +48,10 @@ class DynamicImporter(object):
         path, namespace = fullname.rsplit('.', 1)
         if path != self.path:
             return
-        try:
-            repository.require(namespace)
-        except RepositoryError, e:
-            logging.exception(e)
+
+        if not repository.enumerate(namespace):
+            logging.error('Could not find any typelib for %s', namespace)
+            return None
         else:
             return self
 
@@ -69,18 +69,10 @@ class DynamicImporter(object):
         dynamic_module = DynamicModule(namespace)
         modules[namespace] = dynamic_module
 
-        overrides_modules = __import__('gi.overrides', fromlist=[namespace])
-        overrides_module = getattr(overrides_modules, namespace, None)
-
-        if overrides_module is not None:
-            module = ModuleProxy(fullname, namespace, dynamic_module, overrides_module)
-        else:
-            module = dynamic_module
-
-        module.__file__ = '<%s>' % fullname
-        module.__loader__ = self
+        dynamic_module.__file__ = '<%s>' % fullname
+        dynamic_module.__loader__ = self
 
-        sys.modules[fullname] = module
+        sys.modules[fullname] = dynamic_module
 
-        return module
+        return dynamic_module
 
diff --git a/gi/module.py b/gi/module.py
index e149986..36a5e75 100644
--- a/gi/module.py
+++ b/gi/module.py
@@ -64,6 +64,7 @@ def get_parent_for_object(object_info):
     module = __import__('gi.repository.%s' % namespace, fromlist=[name])
     return getattr(module, name)
 
+
 def get_interfaces_for_object(object_info):
     interfaces = []
     for interface_info in object_info.get_interfaces():
@@ -75,12 +76,19 @@ def get_interfaces_for_object(object_info):
     return interfaces
 
 
-class DynamicModule(object):
+class IntrospectionModule(object):
 
-    def __init__(self, namespace):
+    def __init__(self, namespace, version=None):
+        repository.require(namespace, version)
         self._namespace = namespace
+        self.version = version
         self.__name__ = 'gi.repository.' + namespace
 
+        repository.require(self._namespace, self.version)
+
+        if self.version is None:
+            self.version = repository.get_version(self._namespace)
+
     def __getattr__(self, name):
         info = repository.find_by_name(self._namespace, name)
         if not info:
@@ -165,7 +173,7 @@ class DynamicModule(object):
         return "<DynamicModule %r from %r>" % (self._namespace, path)
 
 
-class DynamicGObjectModule(DynamicModule):
+class DynamicGObjectModule(IntrospectionModule):
     """Wrapper for the GObject module
 
     This class allows us to access both the static PyGObject module and the GI GObject module
@@ -182,12 +190,11 @@ class DynamicGObjectModule(DynamicModule):
     """
 
     def __init__(self):
-        self._namespace = 'GObject'
-        self._module = gobject
+        IntrospectionModule.__init__(self, namespace='GObject')
 
     def __getattr__(self, name):
         # first see if this attr is in the gobject module
-        attr = getattr(self._module, name, None)
+        attr = getattr(gobject, name, None)
 
         # if not in module assume request for an attr exported through GI
         if attr is None:
@@ -195,23 +202,34 @@ class DynamicGObjectModule(DynamicModule):
 
         return attr
 
-class ModuleProxy(object):
-
-    def __init__(self, name, namespace, dynamic_module, overrides_module):
-        self.__name__ = name
 
+class DynamicModule(object):
+    def __init__(self, namespace):
         self._namespace = namespace
-        self._dynamic_module = dynamic_module
-        self._overrides_module = overrides_module
+        self.introspection_module = None
+        self._version = None
+        self._overrides_module = None
+
+    def require_version(self, version):
+        if self.introspection_module is not None and \
+                self.introspection_module.version != version:
+            raise RuntimeError('Module has been already loaded ')
+        self._version = version
+
+    def _import(self):
+        self.introspection_module = IntrospectionModule(self._namespace,
+                                                        self._version)
+
+        overrides_modules = __import__('gi.overrides', fromlist=[self._namespace])
+        self._overrides_module = getattr(overrides_modules, self._namespace, None)
 
     def __getattr__(self, name):
-        override_exports = getattr(self._overrides_module, '__all__', ())
-        if (name in override_exports):
-            attribute = getattr(self._overrides_module, name, None)
-        else:
-            attribute = getattr(self._dynamic_module, name)
-        return attribute
+        if self.introspection_module is None:
+            self._import()
 
-    def __str__(self):
-        return "<ModuleProxy %r>" % self.__name__
+        if self._overrides_module is not None:
+            override_exports = getattr(self._overrides_module, '__all__', ())
+            if name in override_exports:
+                return getattr(self._overrides_module, name, None)
 
+        return getattr(self.introspection_module, name)
diff --git a/gi/overrides/GIMarshallingTests.py b/gi/overrides/GIMarshallingTests.py
index 768efd7..ee01495 100644
--- a/gi/overrides/GIMarshallingTests.py
+++ b/gi/overrides/GIMarshallingTests.py
@@ -21,7 +21,7 @@
 from ..types import override
 from ..importer import modules
 
-GIMarshallingTests = modules['GIMarshallingTests']
+GIMarshallingTests = modules['GIMarshallingTests'].introspection_module
 
 __all__ = []
 
diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py
index 4eaff08..f6cc287 100644
--- a/gi/overrides/Gdk.py
+++ b/gi/overrides/Gdk.py
@@ -22,7 +22,7 @@
 from ..types import override
 from ..importer import modules
 
-Gdk = modules['Gdk']
+Gdk = modules['Gdk'].introspection_module
 
 __all__ = []
 
diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
index 38a90b3..a655e93 100644
--- a/gi/overrides/Gtk.py
+++ b/gi/overrides/Gtk.py
@@ -25,7 +25,7 @@ from gi.repository import GObject
 from ..types import override
 from ..importer import modules
 
-Gtk = modules['Gtk']
+Gtk = modules['Gtk'].introspection_module
 __all__ = []
 
 class ActionGroup(Gtk.ActionGroup):
diff --git a/gi/pygi-repository.c b/gi/pygi-repository.c
index 783b4aa..5d3d793 100644
--- a/gi/pygi-repository.c
+++ b/gi/pygi-repository.c
@@ -60,6 +60,35 @@ PyTypeObject PyGIRepository_Type = {
 };
 
 static PyObject *
+_wrap_g_irepository_enumerate (PyGIRepository *self,
+                               PyObject       *args,
+                               PyObject       *kwargs)
+{
+    static char *kwlist[] = { "namespace", NULL };
+    const char *namespace_;
+    GList *versions, *item;
+    PyObject *ret = NULL;
+
+    if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s:Repository.enumerate",
+                                      kwlist, &namespace_)) {
+        return NULL;
+    }
+
+    versions = g_irepository_enumerate (self->repository, namespace_);
+    ret = PyList_New(0);
+    for (item = versions; item; item = item->next) {
+        char *version = item->data;
+        PyObject *py_version = PyString_FromString (version);
+        PyList_Append(ret, py_version);
+        Py_DECREF(py_version);
+        g_free (version);
+    }
+    g_list_free(versions);
+
+    return ret;
+}
+
+static PyObject *
 _wrap_g_irepository_get_default (PyObject *self)
 {
     static PyGIRepository *repository = NULL;
@@ -91,7 +120,7 @@ _wrap_g_irepository_require (PyGIRepository *self,
     GTypelib *typelib;
     GError *error;
 
-    if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|sO:Repository.require",
+    if (!PyArg_ParseTupleAndKeywords (args, kwargs, "s|zO:Repository.require",
                                       kwlist, &namespace_, &version, &lazy)) {
         return NULL;
     }
@@ -210,12 +239,37 @@ _wrap_g_irepository_get_typelib_path (PyGIRepository *self,
     return PyString_FromString (typelib_path);
 }
 
+static PyObject *
+_wrap_g_irepository_get_version (PyGIRepository *self,
+                                 PyObject       *args,
+                                 PyObject       *kwargs)
+{
+    static char *kwlist[] = { "namespace", NULL };
+    const char *namespace_;
+    const gchar *version;
+
+    if (!PyArg_ParseTupleAndKeywords (args, kwargs,
+                                      "s:Repository.get_version", kwlist, &namespace_)) {
+        return NULL;
+    }
+
+    version = g_irepository_get_version (self->repository, namespace_);
+    if (version == NULL) {
+        PyErr_Format (PyExc_RuntimeError, "Namespace '%s' not loaded", namespace_);
+        return NULL;
+    }
+
+    return PyString_FromString (version);
+}
+
 static PyMethodDef _PyGIRepository_methods[] = {
+    { "enumerate", (PyCFunction) _wrap_g_irepository_enumerate, METH_VARARGS | METH_KEYWORDS },
     { "get_default", (PyCFunction) _wrap_g_irepository_get_default, METH_STATIC | METH_NOARGS },
     { "require", (PyCFunction) _wrap_g_irepository_require, METH_VARARGS | METH_KEYWORDS },
     { "get_infos", (PyCFunction) _wrap_g_irepository_get_infos, METH_VARARGS | METH_KEYWORDS },
     { "find_by_name", (PyCFunction) _wrap_g_irepository_find_by_name, METH_VARARGS | METH_KEYWORDS },
     { "get_typelib_path", (PyCFunction) _wrap_g_irepository_get_typelib_path, METH_VARARGS | METH_KEYWORDS },
+    { "get_version", (PyCFunction) _wrap_g_irepository_get_version, METH_VARARGS | METH_KEYWORDS },
     { NULL, NULL, 0 }
 };
 



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