summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon van der Linden <svdlinden@src.gnome.org>2010-01-22 13:41:21 +0100
committerSimon van der Linden <svdlinden@src.gnome.org>2010-01-22 13:41:21 +0100
commiteaf7cb8ebb7e34f9493ac83b2f04af4dcf45f40f (patch)
tree92c184f82369ffc181701450fe4045ac0cef2ef3
parentb11cf2595987c1f0fc4ffd834f07c98b92aa2355 (diff)
downloadpygi-eaf7cb8ebb7e34f9493ac83b2f04af4dcf45f40f.tar.gz
pygi-eaf7cb8ebb7e34f9493ac83b2f04af4dcf45f40f.tar.xz
pygi-eaf7cb8ebb7e34f9493ac83b2f04af4dcf45f40f.zip
Restore the overrides support
Add a ModuleProxy in front of the DynamicModule when an overrides module is present. There is no need for an overrides module to be a class; it can just be a module. Add an override decorator to override the wrapper of a registered type. Adapt Gdk and Gtk accordingly. Add tests. https://bugzilla.gnome.org/show_bug.cgi?id=602830
-rw-r--r--gi/importer.py40
-rw-r--r--gi/module.py43
-rw-r--r--gi/overrides/Gdk.py42
-rw-r--r--gi/overrides/Gtk.py16
-rw-r--r--gi/types.py6
-rw-r--r--tests/libtestgi.c105
-rw-r--r--tests/libtestgi.h49
-rw-r--r--tests/test_gi.py36
8 files changed, 273 insertions, 64 deletions
diff --git a/gi/importer.py b/gi/importer.py
index f283a41..ad9ede2 100644
--- a/gi/importer.py
+++ b/gi/importer.py
@@ -26,10 +26,11 @@ import sys
import gobject
from ._gi import Repository, RepositoryError
-from .module import DynamicModule
+from .module import DynamicModule, ModuleProxy
repository = Repository.get_default()
+modules = {}
class DynamicImporter(object):
@@ -39,17 +40,6 @@ class DynamicImporter(object):
def __init__(self, path):
self.path = path
- def _create_module(self, module_type, name, namespace):
- module = module_type.__new__(module_type)
- module.__dict__ = {
- '__file__': '<%s>' % name,
- '__name__': name,
- '__namespace__': namespace,
- '__loader__': self
- }
- module.__init__()
- return module
-
def find_module(self, fullname, path=None):
if not fullname.startswith(self.path):
return
@@ -75,23 +65,21 @@ class DynamicImporter(object):
sys.modules[fullname] = gobject
return gobject
- module_type = DynamicModule
- module = self._create_module(module_type, fullname, namespace)
- sys.modules[fullname] = module
+ dynamic_module = DynamicModule(namespace)
+ modules[namespace] = dynamic_module
- # Look for an overrides module
- overrides_name = 'gi.overrides.%s' % namespace
- overrides_type_name = '%sModule' % namespace
- try:
+ overrides_modules = __import__('gi.overrides', fromlist=[namespace])
+ overrides_module = getattr(overrides_modules, namespace, None)
- overrides_module = __import__(overrides_name, fromlist=[overrides_type_name])
- module_type = getattr(overrides_module, overrides_type_name)
- except ImportError, e:
- pass
+ if overrides_module is not None:
+ module = ModuleProxy(fullname, namespace, dynamic_module, overrides_module)
+ else:
+ module = dynamic_module
- if module_type is not DynamicModule:
- module = self._create_module(module_type, fullname, namespace)
- sys.modules[fullname] = module
+ module.__file__ = '<%s>' % fullname
+ module.__loader__ = self
+
+ sys.modules[fullname] = module
return module
diff --git a/gi/module.py b/gi/module.py
index 72a6a53..61fbdfc 100644
--- a/gi/module.py
+++ b/gi/module.py
@@ -75,15 +75,11 @@ def get_interfaces_for_object(object_info):
class DynamicModule(object):
- def __str__(self):
- path = repository.get_typelib_path(self.__namespace__)
- return "<dynamic module %r from %r>" % (self.__name__, path)
+ def __init__(self, namespace):
+ self._namespace = namespace
def __getattr__(self, name):
- if self.__dict__.has_key(name):
- return self.__dict__[name]
-
- info = repository.find_by_name(self.__namespace__, name)
+ info = repository.find_by_name(self._namespace, name)
if not info:
raise AttributeError("%r object has no attribute %r" % (
self.__class__.__name__, name))
@@ -139,7 +135,7 @@ class DynamicModule(object):
name = info.get_name()
dict_ = {
'__info__': info,
- '__module__': self.__namespace__,
+ '__module__': self._namespace,
'__gtype__': g_type
}
value = metaclass(name, bases, dict_)
@@ -158,10 +154,29 @@ class DynamicModule(object):
self.__dict__[name] = value
return value
- @property
- def __members__(self):
- r = []
- for type_info in repository.get_infos(self.__namespace__):
- r.append(type_info.get_name())
- return r
+ def __repr__(self):
+ path = repository.get_typelib_path(self._namespace)
+ return "<DynamicModule %r from %r>" % (self._namespace, path)
+
+
+class ModuleProxy(object):
+
+ def __init__(self, name, namespace, dynamic_module, overrides_module):
+ self.__name__ = name
+
+ self._namespace = namespace
+ self._dynamic_module = dynamic_module
+ self._overrides_module = overrides_module
+
+ def __getattr__(self, name):
+ attribute = getattr(self._overrides_module, name, None)
+ exports = getattr(self._overrides_module, '__all__', ())
+ if attribute is not None and attribute not in exports:
+ attribute = None
+ if attribute is None:
+ attribute = getattr(self._dynamic_module, name)
+ return attribute
+
+ def __str__(self):
+ return "<ModuleProxy %r>" % self.__name__
diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py
index e3e2d29..2662046 100644
--- a/gi/overrides/Gdk.py
+++ b/gi/overrides/Gdk.py
@@ -1,21 +1,33 @@
-import sys
+from ..types import override
+from ..importer import modules
+
+Gdk = modules['Gdk']
+
+
+class Rectangle(Gdk.Rectangle):
-from ..module import DynamicModule
+ def __init__(self, x, y, width, height):
+ Gdk.Rectangle.__init__(self)
+ self.x = x
+ self.y = y
+ self.width = width
+ self.height = height
-class GdkModule(DynamicModule):
+ def __new__(cls, *args, **kwargs):
+ return Gdk.Rectangle.__new__(cls)
- def __init__(self):
- super(GdkModule, self).__init__()
+ def __repr__(self):
+ return '<Gdk.Rectangle(x=%d, y=%d, width=%d, height=%d)>' % (
+ self.x, self.y, self.width, self.height)
- initialized, argv = self.init_check(tuple(sys.argv))
- if not initialized:
- raise RuntimeError("Gdk couldn't be initialized")
+Rectangle = override(Rectangle)
- def rectangle_new(self, x, y, width, height):
- rectangle = self.Rectangle()
- rectangle.x = x
- rectangle.y = y
- rectangle.width = width
- rectangle.height = height
- return rectangle
+__all__ = [Rectangle]
+
+
+import sys
+
+initialized, argv = Gdk.init_check(sys.argv)
+if not initialized:
+ raise RuntimeError("Gdk couldn't be initialized")
diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
index b4e9596..0f5d46a 100644
--- a/gi/overrides/Gtk.py
+++ b/gi/overrides/Gtk.py
@@ -1,15 +1,13 @@
-import sys
+from ..importer import modules
-from ..module import DynamicModule
+Gtk = modules['Gtk']
-class GtkModule(DynamicModule):
- import keysyms
+__all__ = []
- def __init__(self):
- super(GtkModule, self).__init__()
- initialized, argv = self.init_check(tuple(sys.argv))
- if not initialized:
- raise RuntimeError("Gtk couldn't be initialized")
+import sys
+initialized, argv = Gtk.init_check(sys.argv)
+if not initialized:
+ raise RuntimeError("Gtk couldn't be initialized")
diff --git a/gi/types.py b/gi/types.py
index e4d7c5f..b7061bd 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -126,3 +126,9 @@ class StructMeta(type, MetaClassHelper):
cls._setup_methods()
cls._setup_constructors()
+
+def override(type_):
+ g_type = type_.__info__.get_g_type()
+ if g_type != gobject.TYPE_INVALID:
+ g_type.pytype = type_
+ return type_
diff --git a/tests/libtestgi.c b/tests/libtestgi.c
index a8a77a5..c3899a6 100644
--- a/tests/libtestgi.c
+++ b/tests/libtestgi.c
@@ -3477,3 +3477,108 @@ test_gi_int_return_ptr_null (void)
return NULL;
}
+
+TestGIOverridesStruct *
+test_gi_overrides_struct_copy (TestGIOverridesStruct *struct_)
+{
+ TestGIOverridesStruct *new_struct;
+
+ new_struct = g_slice_new (TestGIOverridesStruct);
+
+ *new_struct = *struct_;
+
+ return new_struct;
+}
+
+static void
+test_gi_overrides_struct_free (TestGIOverridesStruct *struct_)
+{
+ g_slice_free (TestGIOverridesStruct, struct_);
+}
+
+GType
+test_gi_overrides_struct_get_type (void)
+{
+ static GType type = 0;
+
+ if (type == 0) {
+ type = g_boxed_type_register_static ("TestGIOverridesStruct",
+ (GBoxedCopyFunc) test_gi_overrides_struct_copy,
+ (GBoxedFreeFunc) test_gi_overrides_struct_free);
+ }
+
+ return type;
+}
+
+TestGIOverridesStruct *
+test_gi_overrides_struct_new (void)
+{
+ return g_slice_new (TestGIOverridesStruct);
+}
+
+glong
+test_gi_overrides_struct_method (TestGIOverridesStruct *struct_)
+{
+ return 42;
+}
+
+
+/**
+ * test_gi__overrides_struct_return:
+ *
+ * Returns: (transfer full):
+ */
+TestGIOverridesStruct *
+test_gi__overrides_struct_return (void)
+{
+ return test_gi_overrides_struct_new();
+}
+
+
+G_DEFINE_TYPE (TestGIOverridesObject, test_gi_overrides_object, G_TYPE_OBJECT);
+
+static void
+test_gi_overrides_object_init (TestGIOverridesObject *object)
+{
+}
+
+static void
+test_gi_overrides_object_finalize (GObject *object)
+{
+ G_OBJECT_CLASS (test_gi_overrides_object_parent_class)->finalize (object);
+}
+
+static void
+test_gi_overrides_object_class_init (TestGIOverridesObjectClass *klass)
+{
+ GObjectClass* object_class = G_OBJECT_CLASS (klass);
+#if 0
+ GObjectClass* parent_class = G_OBJECT_CLASS (klass);
+#endif
+
+ object_class->finalize = test_gi_overrides_object_finalize;
+}
+
+TestGIOverridesObject *
+test_gi_overrides_object_new (void)
+{
+ return g_object_new (TESTGI_TYPE_OVERRIDES_OBJECT, NULL);
+}
+
+glong
+test_gi_overrides_object_method (TestGIOverridesObject *object)
+{
+ return 42;
+}
+
+
+/**
+ * test_gi__overrides_object_return:
+ *
+ * Returns: (transfer full):
+ */
+TestGIOverridesObject *
+test_gi__overrides_object_return (void)
+{
+ return g_object_new (TESTGI_TYPE_OVERRIDES_OBJECT, NULL);
+}
diff --git a/tests/libtestgi.h b/tests/libtestgi.h
index 1620096..970d01b 100644
--- a/tests/libtestgi.h
+++ b/tests/libtestgi.h
@@ -662,4 +662,53 @@ gint *test_gi_int_return_ptr_null (void);
void test_gi_int_in_ptr_null (gint *int_);
+/* Overrides */
+
+#define TESTGI_OVERRIDES_CONSTANT 42
+
+
+typedef struct {
+ glong long_;
+} TestGIOverridesStruct;
+
+GType test_gi_overrides_struct_get_type (void) G_GNUC_CONST;
+
+TestGIOverridesStruct *test_gi_overrides_struct_new (void);
+
+glong test_gi_overrides_struct_method (TestGIOverridesStruct *struct_);
+
+TestGIOverridesStruct *test_gi__overrides_struct_return (void);
+
+
+#define TESTGI_TYPE_OVERRIDES_OBJECT (test_gi_overrides_object_get_type ())
+#define TESTGI_OVERRIDES_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TESTGI_TYPE_OVERRIDES_OBJECT, TestGIOverridesObject))
+#define TESTGI_OVERRIDES_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), TESTGI_TYPE_OVERRIDES_OBJECT, TestGIOverridesObjectClass))
+#define TESTGI_IS_OVERRIDES_OBJECT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TESTGI_TYPE_OVERRIDES_OBJECT))
+#define TESTGI_IS_OVERRIDES_OBJECT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), TESTGI_TYPE_OVERRIDES_OBJECT))
+#define TESTGI_OVERRIDES_OBJECT_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), TESTGI_TYPE_OVERRIDES_OBJECT, TestGIOverridesObjectClass))
+
+typedef struct _TestGIOverridesObjectClass TestGIOverridesObjectClass;
+typedef struct _TestGIOverridesObject TestGIOverridesObject;
+
+struct _TestGIOverridesObjectClass
+{
+ GObjectClass parent_class;
+};
+
+struct _TestGIOverridesObject
+{
+ GObject parent_instance;
+
+ glong long_;
+};
+
+GType test_gi_overrides_object_get_type (void) G_GNUC_CONST;
+
+TestGIOverridesObject *test_gi_overrides_object_new (void);
+
+glong test_gi_overrides_object_method (TestGIOverridesObject *object);
+
+
+TestGIOverridesObject *test_gi__overrides_object_return (void);
+
#endif /* __TEST_GI_H__ */
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 2cbb2eb..0d97915 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1500,3 +1500,39 @@ class TestInterfaces(unittest.TestCase):
instance = TestInterfaceImpl()
self.assertTrue(isinstance(instance, TestGI.Interface))
+
+class TestOverrides(unittest.TestCase):
+
+ def test_constant(self):
+ self.assertEquals(TestGI.OVERRIDES_CONSTANT, 7)
+
+ def test_struct(self):
+ # Test that the constructor has been overridden.
+ struct = TestGI.OverridesStruct(42)
+
+ # Test that the method has been overridden.
+ self.assertEquals(6, struct.method())
+
+ del struct
+
+ # Test that the overrides wrapper has been registered.
+ struct = TestGI.overrides_struct_return()
+
+ self.assertTrue(isinstance(struct, TestGI.OverridesStruct))
+
+ del struct
+
+ def test_struct(self):
+ # Test that the constructor has been overridden.
+ object_ = TestGI.OverridesObject(42)
+
+ # Test that the alternate constructor has been overridden.
+ object_ = TestGI.OverridesObject.new(42)
+
+ # Test that the method has been overridden.
+ self.assertEquals(6, object_.method())
+
+ # Test that the overrides wrapper has been registered.
+ object_ = TestGI.overrides_object_return()
+
+ self.assertTrue(isinstance(object_, TestGI.OverridesObject))