[pygobject] Add protection against attempts at importing static bindings



commit d70403357d6b510356dd375304fb97e458fd12b2
Author: Simon Feltman <sfeltman src gnome org>
Date:   Tue Aug 5 22:45:46 2014 -0700

    Add protection against attempts at importing static bindings
    
    Clobber gobject, gio, glib, gtk, and gtk.gdk in sys.modules upon importing
    gi with dummy modules which produce an error upon access.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=709183

 gi/__init__.py                 |   25 ++++++++++++++++++++++---
 tests/test_import_machinery.py |   24 ++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 3 deletions(-)
---
diff --git a/gi/__init__.py b/gi/__init__.py
index df6843c..3ef2289 100644
--- a/gi/__init__.py
+++ b/gi/__init__.py
@@ -27,12 +27,17 @@ __path__ = extend_path(__path__, __name__)
 import sys
 import os
 import importlib
+import types
+
+_static_binding_error = ('When using gi.repository you must not import static '
+                         'modules like "gobject". Please change all occurrences '
+                         'of "import gobject" to "from gi.repository import GObject". '
+                         'See: https://bugzilla.gnome.org/show_bug.cgi?id=709183')
 
 # we can't have pygobject 2 loaded at the same time we load the internal _gobject
 if 'gobject' in sys.modules:
-    raise ImportError('When using gi.repository you must not import static '
-                      'modules like "gobject". Please change all occurrences '
-                      'of "import gobject" to "from gi.repository import GObject".')
+    raise ImportError(_static_binding_error)
+
 
 from . import _gi
 from ._gi import _gobject
@@ -50,6 +55,20 @@ version_info = _gobject.pygobject_version[:]
 __version__ = "{0}.{1}.{2}".format(*version_info)
 
 
+class _DummyStaticModule(types.ModuleType):
+    __path__ = None
+
+    def __getattr__(self, name):
+        raise RuntimeError(_static_binding_error)
+
+
+sys.modules['glib'] = _DummyStaticModule('glib', _static_binding_error)
+sys.modules['gobject'] = _DummyStaticModule('gobject', _static_binding_error)
+sys.modules['gio'] = _DummyStaticModule('gio', _static_binding_error)
+sys.modules['gtk'] = _DummyStaticModule('gtk', _static_binding_error)
+sys.modules['gtk.gdk'] = _DummyStaticModule('gtk.gdk', _static_binding_error)
+
+
 def check_version(version):
     if isinstance(version, str):
         version_list = tuple(map(int, version.split(".")))
diff --git a/tests/test_import_machinery.py b/tests/test_import_machinery.py
index 42b4bf8..e4c3a7b 100644
--- a/tests/test_import_machinery.py
+++ b/tests/test_import_machinery.py
@@ -58,6 +58,30 @@ class TestModule(unittest.TestCase):
         # Restore the previous cache
         gi.module._introspection_modules = old_modules
 
+    def test_static_binding_protection(self):
+        # Importing old static bindings once gi has been imported should not
+        # crash but instead give back a dummy module which produces RuntimeErrors
+        # on access.
+        with self.assertRaises(RuntimeError):
+            import gobject
+            gobject.anything
+
+        with self.assertRaises(RuntimeError):
+            import glib
+            glib.anything
+
+        with self.assertRaises(RuntimeError):
+            import gio
+            gio.anything
+
+        with self.assertRaises(RuntimeError):
+            import gtk
+            gtk.anything
+
+        with self.assertRaises(RuntimeError):
+            import gtk.gdk
+            gtk.gdk.anything
+
 
 class TestImporter(unittest.TestCase):
     def test_invalid_repository_module_name(self):


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