[pygobject] [API add] Add get_introspection_module for getting un-overridden modules



commit e9624ed1d38c777de2b430e3b0fbae2acbf34956
Author: Simon Feltman <sfeltman src gnome org>
Date:   Wed Oct 24 04:31:26 2012 -0700

    [API add] Add get_introspection_module for getting un-overridden modules
    
    Add gi.module.get_introspection_module to explicitly get a
    wrapped module pulled in through introspection without static
    and python override handling. This API is intended for python
    overrides to use rather than having them access
    gi.importer.modules['<name>']._introspection_module directly.
    Replace aforementioned usage in all overrides.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=686828

 gi/module.py                       |   38 +++++++++++++++++++++++++++++++++--
 gi/overrides/GIMarshallingTests.py |    4 +-
 gi/overrides/GLib.py               |    4 +-
 gi/overrides/Gdk.py                |    6 ++--
 gi/overrides/Gio.py                |    4 +-
 gi/overrides/Gtk.py                |    5 ++-
 gi/overrides/Pango.py              |    4 +-
 tests/test_overrides.py            |   29 +++++++++++++++++++++++++++
 8 files changed, 78 insertions(+), 16 deletions(-)
---
diff --git a/gi/module.py b/gi/module.py
index e115fc7..7e1ae0f 100644
--- a/gi/module.py
+++ b/gi/module.py
@@ -62,6 +62,9 @@ from .types import \
 
 repository = Repository.get_default()
 
+# Cache of IntrospectionModules that have been loaded.
+_introspection_modules = {}
+
 
 def get_parent_for_object(object_info):
     parent_object_info = object_info.get_parent()
@@ -92,7 +95,13 @@ def get_interfaces_for_object(object_info):
 
 
 class IntrospectionModule(object):
+    """An object which wraps an introspection typelib.
 
+    This wrapping creates a python module like representation of the typelib
+    using gi repository as a foundation. Accessing attributes of the module
+    will dynamically pull them in and create wrappers for the members.
+    These members are then cached on this introspection module.
+    """
     def __init__(self, namespace, version=None):
         repository.require(namespace, version)
         self._namespace = namespace
@@ -203,6 +212,9 @@ class IntrospectionModule(object):
         else:
             raise NotImplementedError(info)
 
+        # Cache the newly created attribute wrapper which will then be
+        # available directly on this introspection module instead of being
+        # retrieved through the __getattr__ we are currently in.
         self.__dict__[name] = wrapper
         return wrapper
 
@@ -229,7 +241,29 @@ class IntrospectionModule(object):
         return list(result)
 
 
+def get_introspection_module(namespace):
+    """
+    :Returns:
+        An object directly wrapping the gi module without overrides.
+    """
+    if namespace in _introspection_modules:
+        return _introspection_modules[namespace]
+
+    version = gi.get_required_version(namespace)
+    module = IntrospectionModule(namespace, version)
+    _introspection_modules[namespace] = module
+    return module
+
+
 class DynamicModule(types.ModuleType):
+    """A module composed of an IntrospectionModule and an overrides module.
+
+    DynamicModule wraps up an IntrospectionModule and an overrides module
+    into a single accessible module. This is what is returned from statements
+    like "from gi.repository import Foo". Accessing attributes on a DynamicModule
+    will first look overrides (or the gi.overrides.registry cache) and then
+    in the introspection module if it was not found as an override.
+    """
     def __init__(self, namespace):
         self._namespace = namespace
         self._introspection_module = None
@@ -237,9 +271,7 @@ class DynamicModule(types.ModuleType):
         self.__path__ = None
 
     def _load(self):
-        version = gi.get_required_version(self._namespace)
-        self._introspection_module = IntrospectionModule(self._namespace,
-                                                         version)
+        self._introspection_module = get_introspection_module(self._namespace)
         try:
             overrides_modules = __import__('gi.overrides', fromlist=[self._namespace])
             self._overrides_module = getattr(overrides_modules, self._namespace, None)
diff --git a/gi/overrides/GIMarshallingTests.py b/gi/overrides/GIMarshallingTests.py
index a25eda7..af2529a 100644
--- a/gi/overrides/GIMarshallingTests.py
+++ b/gi/overrides/GIMarshallingTests.py
@@ -19,9 +19,9 @@
 # USA
 
 from ..overrides import override
-from ..importer import modules
+from ..module import get_introspection_module
 
-GIMarshallingTests = modules['GIMarshallingTests']._introspection_module
+GIMarshallingTests = get_introspection_module('GIMarshallingTests')
 
 __all__ = []
 
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index b4d74be..22de6bf 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -21,11 +21,11 @@
 
 import signal
 
-from ..importer import modules
+from ..module import get_introspection_module
 from .._gi import variant_new_tuple, variant_type_from_string, source_new, source_set_callback
 from ..overrides import override, deprecated
 
-GLib = modules['GLib']._introspection_module
+GLib = get_introspection_module('GLib')
 
 __all__ = []
 
diff --git a/gi/overrides/Gdk.py b/gi/overrides/Gdk.py
index 20ef910..653b3df 100644
--- a/gi/overrides/Gdk.py
+++ b/gi/overrides/Gdk.py
@@ -20,11 +20,11 @@
 # USA
 
 from ..overrides import override
-from ..importer import modules
+from ..module import get_introspection_module
 
 import sys
 
-Gdk = modules['Gdk']._introspection_module
+Gdk = get_introspection_module('Gdk')
 
 __all__ = []
 
@@ -287,7 +287,7 @@ for event_class in event_member_classes:
 
 class DragContext(Gdk.DragContext):
     def finish(self, success, del_, time):
-        Gtk = modules['Gtk']._introspection_module
+        Gtk = get_introspection_module('Gtk')
         Gtk.drag_finish(self, success, del_, time)
 
 DragContext = override(DragContext)
diff --git a/gi/overrides/Gio.py b/gi/overrides/Gio.py
index 9f96440..6ecd1c4 100644
--- a/gi/overrides/Gio.py
+++ b/gi/overrides/Gio.py
@@ -19,13 +19,13 @@
 # USA
 
 from ..overrides import override
-from ..importer import modules
+from ..module import get_introspection_module
 
 from gi.repository import GLib
 
 import sys
 
-Gio = modules['Gio']._introspection_module
+Gio = get_introspection_module('Gio')
 
 __all__ = []
 
diff --git a/gi/overrides/Gtk.py b/gi/overrides/Gtk.py
index 5eab41b..1856a4a 100644
--- a/gi/overrides/Gtk.py
+++ b/gi/overrides/Gtk.py
@@ -22,7 +22,7 @@
 import sys
 from gi.repository import GObject
 from ..overrides import override
-from ..importer import modules
+from ..module import get_introspection_module
 
 if sys.version_info >= (3, 0):
     _basestring = str
@@ -31,7 +31,8 @@ else:
     _basestring = basestring
     _callable = callable
 
-Gtk = modules['Gtk']._introspection_module
+Gtk = get_introspection_module('Gtk')
+
 __all__ = []
 
 if Gtk._version == '2.0':
diff --git a/gi/overrides/Pango.py b/gi/overrides/Pango.py
index 34c76cc..15d5edc 100644
--- a/gi/overrides/Pango.py
+++ b/gi/overrides/Pango.py
@@ -19,9 +19,9 @@
 # USA
 
 from ..overrides import override
-from ..importer import modules
+from ..module import get_introspection_module
 
-Pango = modules['Pango']._introspection_module
+Pango = get_introspection_module('Pango')
 
 __all__ = []
 
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index dd2aa6a..e1af1f1 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -4,6 +4,8 @@
 import unittest
 
 import gi.overrides
+import gi.module
+
 try:
     from gi.repository import Regress
     Regress  # pyflakes
@@ -27,3 +29,30 @@ class TestRegistry(unittest.TestCase):
         # Regress override is in tests/gi/overrides, separate from gi/overrides
         # https://bugzilla.gnome.org/show_bug.cgi?id=680913
         self.assertEqual(Regress.REGRESS_OVERRIDE, 42)
+
+
+class TestModule(unittest.TestCase):
+    # Tests for gi.module
+
+    def test_get_introspection_module_caching(self):
+        # This test attempts to minimize side effects by
+        # using a DynamicModule directly instead of going though:
+        # from gi.repository import Foo
+
+        # Clear out introspection module cache before running this test.
+        old_modules = gi.module._introspection_modules
+        gi.module._introspection_modules = {}
+
+        mod_name = 'GIMarshallingTests'
+        mod1 = gi.module.get_introspection_module(mod_name)
+        mod2 = gi.module.get_introspection_module(mod_name)
+        self.assertTrue(mod1 is mod2)
+
+        # Using a DynamicModule will use get_introspection_module internally
+        # in its _load method.
+        mod_overridden = gi.module.DynamicModule(mod_name)
+        mod_overridden._load()
+        self.assertTrue(mod1 is mod_overridden._introspection_module)
+
+        # Restore the previous cache
+        gi.module._introspection_modules = old_modules



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