diff options
author | Simon van der Linden <svdlinden@src.gnome.org> | 2010-01-22 13:41:21 +0100 |
---|---|---|
committer | Simon van der Linden <svdlinden@src.gnome.org> | 2010-01-22 13:41:21 +0100 |
commit | eaf7cb8ebb7e34f9493ac83b2f04af4dcf45f40f (patch) | |
tree | 92c184f82369ffc181701450fe4045ac0cef2ef3 | |
parent | b11cf2595987c1f0fc4ffd834f07c98b92aa2355 (diff) | |
download | pygi-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.py | 40 | ||||
-rw-r--r-- | gi/module.py | 43 | ||||
-rw-r--r-- | gi/overrides/Gdk.py | 42 | ||||
-rw-r--r-- | gi/overrides/Gtk.py | 16 | ||||
-rw-r--r-- | gi/types.py | 6 | ||||
-rw-r--r-- | tests/libtestgi.c | 105 | ||||
-rw-r--r-- | tests/libtestgi.h | 49 | ||||
-rw-r--r-- | tests/test_gi.py | 36 |
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)) |