Commit 89c104d1 authored by John (J5) Palmieri's avatar John (J5) Palmieri
Browse files

Add a overrides registry so we can refrence overrides inside the module

* Overrides have a reentrancy issue when doing inheritance.  If an override
  inherits from another override down the stack it won't see the override
  because the module is not finished loading and will inherit from the
  non-overriden object instead.  This causes type errors later.
* By adding the overrides to a registry outside of the module we can order
  registration and make the override available as soon as the class is parsed,
  not when the whole module is parsed.

https://bugzilla.gnome.org/show_bug.cgi?id=633347
parent 878b8f63
......@@ -25,6 +25,8 @@ from __future__ import absolute_import
import os
import gobject
from .overrides import registry
from ._gi import \
Repository, \
FunctionInfo, \
......@@ -47,7 +49,6 @@ from .types import \
repository = Repository.get_default()
def get_parent_for_object(object_info):
parent_object_info = object_info.get_parent()
......@@ -236,6 +237,15 @@ class DynamicModule(object):
override_exports = getattr(self._overrides_module, '__all__', ())
if name in override_exports:
return getattr(self._overrides_module, name, None)
else:
# check the registry just in case the module hasn't loaded yet
# TODO: Only gtypes are registered in the registry right now
# but it would be nice to register all overrides and
# get rid of the module imports. We might actually see a
# speedup.
key = '%s.%s' % (self._namespace, name)
if key in registry:
return registry[key]
return getattr(self.introspection_module, name)
......
......@@ -18,7 +18,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
from ..types import override
from ..overrides import override
from ..importer import modules
GIMarshallingTests = modules['GIMarshallingTests'].introspection_module
......
......@@ -19,7 +19,7 @@
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
# USA
from ..types import override
from ..overrides import override
from ..importer import modules
Gdk = modules['Gdk'].introspection_module
......
......@@ -23,7 +23,7 @@ import sys
import gobject
from gi.repository import Gdk
from gi.repository import GObject
from ..types import override
from ..overrides import override
from ..importer import modules
if sys.version_info >= (3, 0):
......
import gobject
registry = None
class _Registry(dict):
def __setitem__(self, key, value):
'''We do checks here to make sure only submodules of the override
module are added. Key and value should be the same object and come
from the gi.override module.
We add the override to the dict as "override_module.name". For instance
if we were overriding Gtk.Button you would retrive it as such:
registry['Gtk.Button']
'''
if not key == value:
raise KeyError('You have tried to modify the registry. This should only be done by the override decorator')
info = getattr(value, '__info__')
if info == None:
raise KeyError('Can not override a type %s, which is not in a gobject introspection typelib' % value.__name__)
if not value.__module__.startswith('gi.overrides'):
raise KeyError('You have tried to modify the registry outside of the overrides module. This is not allowed')
g_type = info.get_g_type()
assert g_type != gobject.TYPE_NONE
if g_type != gobject.TYPE_INVALID:
g_type.pytype = value
# strip gi.overrides from module name
module = value.__module__[13:]
key = "%s.%s" % (module, value.__name__)
super(_Registry, self).__setitem__(key, value)
def register(self, override_class):
self[override_class] = override_class
registry = _Registry()
def override(type_):
'''Decorator for registering an override'''
registry.register(type_)
return type_
......@@ -162,14 +162,6 @@ class StructMeta(type, MetaClassHelper):
cls._setup_methods()
cls._setup_constructors()
def override(type_):
g_type = type_.__info__.get_g_type()
assert g_type != gobject.TYPE_NONE
if g_type != gobject.TYPE_INVALID:
g_type.pytype = type_
return type_
class Enum(int):
__info__ = None
def __init__(self, value):
......
......@@ -14,6 +14,7 @@ from gi.repository import GObject
from gi.repository import Gdk
from gi.repository import Gtk
import gi.overrides as overrides
import gi.types
class TestGLib(unittest.TestCase):
......@@ -550,3 +551,29 @@ class TestGtk(unittest.TestCase):
self.assertEquals(Gtk.STOCK_CLOSE, button.get_label())
self.assertTrue(button.get_use_stock())
self.assertTrue(button.get_use_underline())
def test_inheritance(self):
for name in overrides.Gtk.__all__:
over = getattr(overrides.Gtk, name)
for element in dir(Gtk):
try:
klass = getattr(Gtk, element)
info = klass.__info__
except (NotImplementedError, AttributeError):
continue
# Get all parent classes and interfaces klass inherits from
if isinstance(info, gi.types.ObjectInfo):
classes = list(info.get_interfaces())
parent = info.get_parent()
while parent.get_name() != "Object":
classes.append(parent)
parent = parent.get_parent()
classes = [kl for kl in classes if kl.get_namespace() == "Gtk"]
else:
continue
for kl in classes:
if kl.get_name() == name:
self.assertTrue(issubclass(klass, over,),
"%r does not inherit from override %r" % (klass, over,))
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