[pygobject/gsoc2009: 40/160] Change the import strategy



commit 7df821f8200db7b64bd0b508f0a2fa6b95900524
Author: Simon van der Linden <svdlinden src gnome org>
Date:   Wed Jul 15 11:50:57 2009 +0200

    Change the import strategy
    
    Dynamic modules should be loaded with 'from gi.repository import <module>' or
    any equivalent form.
    gi.repository is a dummy module whose loader is overridden by a dynamic importer.

 configure.ac               |    1 +
 gi/Makefile.am             |    2 +-
 gi/__init__.py             |    6 ------
 gi/importer.py             |   33 ++++++++++++++++++++-------------
 gi/module.py               |   16 +++++-----------
 gi/pygargument.c           |    4 ++--
 gi/pygirepository.c        |   15 +++++++++++++++
 gi/pygirepository.h        |    2 ++
 gi/repository/Makefile.am  |   11 +++++++++++
 gi/repository/__init__.py  |   28 ++++++++++++++++++++++++++++
 tests/test_girepository.py |    3 +--
 11 files changed, 86 insertions(+), 35 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index c4126f8..ceac95e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -238,6 +238,7 @@ AC_CONFIG_FILES(
   gobject/Makefile
   gio/Makefile
   gi/Makefile
+  gi/repository/Makefile
   gi/overrides/Makefile
   examples/Makefile
   tests/Makefile
diff --git a/gi/Makefile.am b/gi/Makefile.am
index afad920..d4e1e11 100644
--- a/gi/Makefile.am
+++ b/gi/Makefile.am
@@ -1,6 +1,6 @@
 AUTOMAKE_OPTIONS = 1.7
 
-SUBDIRS = overrides
+SUBDIRS = repository overrides
 
 PLATFORM_VERSION = 2.0
 
diff --git a/gi/__init__.py b/gi/__init__.py
index b860987..1f6a31e 100644
--- a/gi/__init__.py
+++ b/gi/__init__.py
@@ -18,9 +18,3 @@
 # 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/gi/importer.py b/gi/importer.py
index 66b6388..dd7f105 100644
--- a/gi/importer.py
+++ b/gi/importer.py
@@ -21,7 +21,6 @@
 # USA
 
 import sys
-import new
 import gobject
 
 from ._gi import Repository
@@ -29,30 +28,41 @@ from .module import DynamicModule
 
 
 repository = Repository.get_default()
-sys.modules['GObject'] = gobject
 
 
 class DynamicImporter(object):
 
     # Note: see PEP302 for the Importer Protocol implemented below.
 
+    def __init__(self, path):
+        self.path = path
+
     def find_module(self, fullname, path=None):
-        # Avoid name clashes, and favour static bindings.
-        if fullname == 'cairo':
-            return None
+        if not fullname.startswith(self.path):
+            return
 
-        if repository.require(fullname):
+        path, namespace = fullname.rsplit('.', 1)
+        if path != self.path:
+            return
+        if repository.require(namespace):
             return self
 
     def load_module(self, fullname):
         if fullname in sys.modules:
             return sys.modules[name]
 
+        path, namespace = fullname.rsplit('.', 1)
+
+        # Workaround for GObject
+        if namespace == 'GObject':
+            sys.modules[fullname] = gobject
+            return gobject
+
         # Look for an overrides module
-        overrides_name = 'gi.overrides.%s' % fullname
+        overrides_name = 'gi.overrides.%s' % namespace
         try:
-            overrides_type_name = '%sModule' % fullname
-            overrides_module = __import__(overrides_name, {}, {}, [overrides_type_name])
+            overrides_type_name = '%sModule' % namespace
+            overrides_module = __import__(overrides_name, fromlist=[overrides_type_name])
             module_type = getattr(overrides_module, overrides_type_name)
         except ImportError, e:
             module_type = DynamicModule
@@ -61,6 +71,7 @@ class DynamicImporter(object):
         module.__dict__ = {
             '__file__': '<%s>' % fullname,
             '__name__': fullname,
+            '__namespace__': namespace,
             '__loader__': self
         }
 
@@ -70,7 +81,3 @@ class DynamicImporter(object):
 
         return module
 
-
-def install_importhook():
-    sys.meta_path.append(DynamicImporter())
-
diff --git a/gi/module.py b/gi/module.py
index bed17d7..4e4d8d0 100644
--- a/gi/module.py
+++ b/gi/module.py
@@ -43,7 +43,6 @@ from .types import \
     GIStruct, \
     Function
 
-
 repository = Repository.get_default()
 
 
@@ -56,16 +55,11 @@ def get_parent_for_object(object_info):
     namespace = parent_object_info.getNamespace()
     name = parent_object_info.getName()
 
-    module = __import__(namespace)
-
-    if isinstance(parent_object_info, UnresolvedInfo):
-        # The module has been imported, try again.
-        parent_object_info = object_info.getParent()
-
-    # Workaround for gobject.Object and gobject.InitiallyUnowned.
-    if module == gobject and name == 'Object' or name == 'InitiallyUnowned':
+    # Workaround for GObject.Object and GObject.InitiallyUnowned.
+    if namespace == 'GObject' and name == 'Object' or name == 'InitiallyUnowned':
         return GObject
 
+    module = __import__('gi.repository.%s' % namespace, fromlist=[name])
     return getattr(module, name)
 
 
@@ -75,7 +69,7 @@ class DynamicModule(object):
         return "<dynamic module %r>" % self.__name__
 
     def __getattr__(self, name):
-        info = repository.find_by_name(self.__name__, name)
+        info = repository.find_by_name(self.__namespace__, name)
         if not info:
             raise AttributeError("%r object has no attribute %r" % (
                     self.__class__.__name__, name))
@@ -128,7 +122,7 @@ class DynamicModule(object):
     @property
     def __members__(self):
         r = []
-        for type_info in repository.get_infos(self.__name__):
+        for type_info in repository.get_infos(self.__namespace__):
             if type_info is None:
                 continue
             r.append(type_info.getName())
diff --git a/gi/pygargument.c b/gi/pygargument.c
index bdd000f..cd22d71 100644
--- a/gi/pygargument.c
+++ b/gi/pygargument.c
@@ -886,7 +886,7 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
                 module_name = g_base_info_get_namespace(interface_info);
                 type_name = g_base_info_get_name(interface_info);
 
-                module = PyImport_ImportModule(module_name);
+                module = pygi_repository_get_py_module(module_name);
                 if (module == NULL) {
                     PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
                     break;
@@ -935,7 +935,7 @@ pyg_argument_to_pyobject(GArgument *arg, GITypeInfo *type_info)
                 module_name = g_base_info_get_namespace(interface_info);
                 type_name = g_base_info_get_name(interface_info);
 
-                module = PyImport_ImportModule(module_name);
+                module = pygi_repository_get_py_module(module_name);
                 if (module == NULL) {
                     PyErr_Format(PyExc_TypeError, "Type %s.%s not defined", module_name, type_name);
                     break;
diff --git a/gi/pygirepository.c b/gi/pygirepository.c
index c640b51..fa8065d 100644
--- a/gi/pygirepository.c
+++ b/gi/pygirepository.c
@@ -227,6 +227,21 @@ static PyMethodDef _PyGIRepository_methods[] = {
     { NULL, NULL, 0 }
 };
 
+PyObject *
+pygi_repository_get_py_module(const char * namespace_)
+{
+    PyObject *py_module;
+    gchar *module_name;
+
+    module_name = g_strconcat("gi.repository.", namespace_, NULL);
+
+    py_module = PyImport_ImportModule(module_name);
+
+    g_free(module_name);
+
+    return py_module;
+}
+
 void
 pygi_repository_register_types(PyObject *m)
 {
diff --git a/gi/pygirepository.h b/gi/pygirepository.h
index 573ecf3..6d519ad 100644
--- a/gi/pygirepository.h
+++ b/gi/pygirepository.h
@@ -26,6 +26,8 @@
 
 G_BEGIN_DECLS
 
+PyObject * pygi_repository_get_py_module(const char * namespace_);
+
 void pygi_repository_register_types(PyObject *m);
 
 G_END_DECLS
diff --git a/gi/repository/Makefile.am b/gi/repository/Makefile.am
new file mode 100644
index 0000000..a95507f
--- /dev/null
+++ b/gi/repository/Makefile.am
@@ -0,0 +1,11 @@
+AUTOMAKE_OPTIONS = 1.7
+PLATFORM_VERSION = 2.0
+
+# gi-repository extension modules
+pkgpyexecdir = $(pyexecdir)/gtk-2.0/gi/repository
+
+# gi-repository python scripts
+pygirepositorydir = $(pkgpyexecdir)
+pygirepository_PYTHON = \
+	__init__.py
+
diff --git a/gi/repository/__init__.py b/gi/repository/__init__.py
new file mode 100644
index 0000000..640fc8e
--- /dev/null
+++ b/gi/repository/__init__.py
@@ -0,0 +1,28 @@
+# -*- Mode: Python; py-indent-offset: 4 -*-
+# vim: tabstop=4 shiftwidth=4 expandtab
+#
+# Copyright (C) 2009 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 sys
+
+from ..importer import DynamicImporter
+
+sys.meta_path.append(DynamicImporter('gi.repository'))
+
+del DynamicImporter
+del sys
diff --git a/tests/test_girepository.py b/tests/test_girepository.py
index 7ddf488..50b9de1 100644
--- a/tests/test_girepository.py
+++ b/tests/test_girepository.py
@@ -6,8 +6,7 @@ import time
 import gobject
 from gobject import constants
 
-import gi
-import Everything
+from gi.repository import Everything
 
 INT8_MIN = -128
 INT16_MIN = -32768



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