Commit eaf7cb8e authored by Simon van der Linden's avatar Simon van der Linden
Browse files

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
parent b11cf259
......@@ -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
......@@ -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__
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")
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")
......@@ -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_
......@@ -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);
}
......@@ -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__ */
......@@ -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))
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment