[pygobject] tests: Make patching in pygtkcompat reversible



commit 21cee6cc4fbc7fb1a28a15840924b0da52b49fca
Author: Christoph Reiter <reiter christoph gmail com>
Date:   Sun Feb 11 16:08:18 2018 +0100

    tests: Make patching in pygtkcompat reversible
    
    Record all the attribute and sys.modules changes and add an API
    for reverting them after tests are completed.
    
    This allows us to run the pygtkcompat tests in the same test process
    as other tests.

 pygtkcompat/pygtkcompat.py                         | 273 ++++++++++++---------
 setup.py                                           |   7 -
 tests/Makefile.am                                  |   4 +-
 tests/runtests.py                                  |   2 +-
 .../{compat_test_pygtk.py => test_pygtkcompat.py}  |  96 ++++++--
 5 files changed, 237 insertions(+), 145 deletions(-)
---
diff --git a/pygtkcompat/pygtkcompat.py b/pygtkcompat/pygtkcompat.py
index 6884ef1d..299e0d18 100644
--- a/pygtkcompat/pygtkcompat.py
+++ b/pygtkcompat/pygtkcompat.py
@@ -51,6 +51,24 @@ import gi
 from gi.repository import GObject
 
 
+_patches = []
+_module_patches = []
+_unset = object()
+_enabled_registry = {}
+
+
+def _patch(obj, name, new_value):
+    old_value = getattr(obj, name, _unset)
+    setattr(obj, name, new_value)
+    _patches.append((obj, name, old_value))
+
+
+def _patch_module(name, new_value):
+    old_value = sys.modules.get(name, _unset)
+    sys.modules[name] = new_value
+    _module_patches.append((name, old_value))
+
+
 def _install_enums(module, dest=None, strip=''):
     if dest is None:
         dest = module
@@ -67,7 +85,7 @@ def _install_enums(module, dest=None, strip=''):
                     name = name.replace(modname + '_', '')
                     if strip and name.startswith(strip):
                         name = name[len(strip):]
-                    setattr(dest, name, enum)
+                    _patch(dest, name, enum)
         except TypeError:
             continue
         try:
@@ -79,14 +97,11 @@ def _install_enums(module, dest=None, strip=''):
                         # FIXME: this happens for some large flags which do not
                         # fit into a long on 32 bit systems
                         continue
-                    setattr(dest, name, flag)
+                    _patch(dest, name, flag)
         except TypeError:
             continue
 
 
-_enabled_registry = {}
-
-
 def _check_enabled(name, version=None):
     """Returns True in case it is already enabled"""
 
@@ -108,20 +123,46 @@ def enable():
 
     # gobject
     from gi.repository import GLib
-    sys.modules['glib'] = GLib
+    _patch_module('glib', GLib)
 
     # gobject
     from gi.repository import GObject
-    sys.modules['gobject'] = GObject
+    _patch_module('gobject', GObject)
     from gi import _propertyhelper
-    sys.modules['gobject.propertyhelper'] = _propertyhelper
+    _patch_module('gobject.propertyhelper', _propertyhelper)
 
     # gio
     from gi.repository import Gio
-    sys.modules['gio'] = Gio
+    _patch_module('gio', Gio)
 
 
-_unset = object()
+def _disable_all():
+    """Reverse all effects of the enable_xxx() calls except for
+    require_version() calls and imports.
+    """
+
+    _enabled_registry.clear()
+
+    for obj, name, old_value in reversed(_patches):
+        if old_value is _unset:
+            delattr(obj, name)
+        else:
+            # try if deleting is enough (for override proxies)
+            delattr(obj, name)
+            if getattr(obj, name, _unset) is not old_value:
+                setattr(obj, name, old_value)
+    del _patches[:]
+
+    for name, old_value in reversed(_module_patches):
+        if old_value is _unset:
+            del sys.modules[name]
+        else:
+            sys.modules[name] = old_value
+    del _module_patches[:]
+
+    reload(sys)
+    if sys.version_info < (3, 0):
+        sys.setdefaultencoding('ascii')
 
 
 def enable_gtk(version='3.0'):
@@ -139,46 +180,46 @@ def enable_gtk(version='3.0'):
     # atk
     gi.require_version('Atk', '1.0')
     from gi.repository import Atk
-    sys.modules['atk'] = Atk
+    _patch_module('atk', Atk)
     _install_enums(Atk)
 
     # pango
     gi.require_version('Pango', '1.0')
     from gi.repository import Pango
-    sys.modules['pango'] = Pango
+    _patch_module('pango', Pango)
     _install_enums(Pango)
 
     # pangocairo
     gi.require_version('PangoCairo', '1.0')
     from gi.repository import PangoCairo
-    sys.modules['pangocairo'] = PangoCairo
+    _patch_module('pangocairo', PangoCairo)
 
     # gdk
     gi.require_version('Gdk', version)
     gi.require_version('GdkPixbuf', '2.0')
     from gi.repository import Gdk
     from gi.repository import GdkPixbuf
-    sys.modules['gtk.gdk'] = Gdk
+    _patch_module('gtk.gdk', Gdk)
     _install_enums(Gdk)
     _install_enums(GdkPixbuf, dest=Gdk)
-    Gdk._2BUTTON_PRESS = 5
-    Gdk.BUTTON_PRESS = 4
-
-    Gdk.screen_get_default = Gdk.Screen.get_default
-    Gdk.Pixbuf = GdkPixbuf.Pixbuf
-    Gdk.PixbufLoader = GdkPixbuf.PixbufLoader.new_with_type
-    Gdk.pixbuf_new_from_data = GdkPixbuf.Pixbuf.new_from_data
-    Gdk.pixbuf_new_from_file = GdkPixbuf.Pixbuf.new_from_file
+    _patch(Gdk, "_2BUTTON_PRESS", 5)
+    _patch(Gdk, "BUTTON_PRESS", 4)
+
+    _patch(Gdk, "screen_get_default", Gdk.Screen.get_default)
+    _patch(Gdk, "Pixbuf", GdkPixbuf.Pixbuf)
+    _patch(Gdk, "PixbufLoader", GdkPixbuf.PixbufLoader.new_with_type)
+    _patch(Gdk, "pixbuf_new_from_data", GdkPixbuf.Pixbuf.new_from_data)
+    _patch(Gdk, "pixbuf_new_from_file", GdkPixbuf.Pixbuf.new_from_file)
     try:
-        Gdk.pixbuf_new_from_file_at_scale = GdkPixbuf.Pixbuf.new_from_file_at_scale
+        _patch(Gdk, "pixbuf_new_from_file_at_scale", GdkPixbuf.Pixbuf.new_from_file_at_scale)
     except AttributeError:
         pass
-    Gdk.pixbuf_new_from_file_at_size = GdkPixbuf.Pixbuf.new_from_file_at_size
-    Gdk.pixbuf_new_from_inline = GdkPixbuf.Pixbuf.new_from_inline
-    Gdk.pixbuf_new_from_stream = GdkPixbuf.Pixbuf.new_from_stream
-    Gdk.pixbuf_new_from_stream_at_scale = GdkPixbuf.Pixbuf.new_from_stream_at_scale
-    Gdk.pixbuf_new_from_xpm_data = GdkPixbuf.Pixbuf.new_from_xpm_data
-    Gdk.pixbuf_get_file_info = GdkPixbuf.Pixbuf.get_file_info
+    _patch(Gdk, "pixbuf_new_from_file_at_size", GdkPixbuf.Pixbuf.new_from_file_at_size)
+    _patch(Gdk, "pixbuf_new_from_inline", GdkPixbuf.Pixbuf.new_from_inline)
+    _patch(Gdk, "pixbuf_new_from_stream", GdkPixbuf.Pixbuf.new_from_stream)
+    _patch(Gdk, "pixbuf_new_from_stream_at_scale", GdkPixbuf.Pixbuf.new_from_stream_at_scale)
+    _patch(Gdk, "pixbuf_new_from_xpm_data", GdkPixbuf.Pixbuf.new_from_xpm_data)
+    _patch(Gdk, "pixbuf_get_file_info", GdkPixbuf.Pixbuf.get_file_info)
 
     orig_get_formats = GdkPixbuf.Pixbuf.get_formats
 
@@ -198,7 +239,7 @@ def enable_gtk(version='3.0'):
             result.append(make_dict(format_))
         return result
 
-    Gdk.pixbuf_get_formats = get_formats
+    _patch(Gdk, "pixbuf_get_formats", get_formats)
 
     orig_get_frame_extents = Gdk.Window.get_frame_extents
 
@@ -212,34 +253,34 @@ def enable_gtk(version='3.0'):
         except TypeError:
             rect = orig_get_frame_extents(window)
         return rect
-    Gdk.Window.get_frame_extents = get_frame_extents
+    _patch(Gdk.Window, "get_frame_extents", get_frame_extents)
 
     orig_get_origin = Gdk.Window.get_origin
 
     def get_origin(self):
         return orig_get_origin(self)[1:]
-    Gdk.Window.get_origin = get_origin
+    _patch(Gdk.Window, "get_origin", get_origin)
 
-    Gdk.screen_width = Gdk.Screen.width
-    Gdk.screen_height = Gdk.Screen.height
+    _patch(Gdk, "screen_width", Gdk.Screen.width)
+    _patch(Gdk, "screen_height", Gdk.Screen.height)
 
     orig_gdk_window_get_geometry = Gdk.Window.get_geometry
 
     def gdk_window_get_geometry(window):
         return orig_gdk_window_get_geometry(window) + (window.get_visual().get_best_depth(),)
-    Gdk.Window.get_geometry = gdk_window_get_geometry
+    _patch(Gdk.Window, "get_geometry", gdk_window_get_geometry)
 
     # gtk
     gi.require_version('Gtk', version)
     from gi.repository import Gtk
-    sys.modules['gtk'] = Gtk
-    Gtk.gdk = Gdk
+    _patch_module('gtk', Gtk)
+    _patch(Gtk, "gdk", Gdk)
 
-    Gtk.pygtk_version = (2, 99, 0)
+    _patch(Gtk, "pygtk_version", (2, 99, 0))
 
-    Gtk.gtk_version = (Gtk.MAJOR_VERSION,
-                       Gtk.MINOR_VERSION,
-                       Gtk.MICRO_VERSION)
+    _patch(Gtk, "gtk_version", (Gtk.MAJOR_VERSION,
+                                Gtk.MINOR_VERSION,
+                                Gtk.MICRO_VERSION))
     _install_enums(Gtk)
 
     # Action
@@ -247,7 +288,7 @@ def enable_gtk(version='3.0'):
     def set_tool_item_type(menuaction, gtype):
         warnings.warn('set_tool_item_type() is not supported',
                       gi.PyGIDeprecationWarning, stacklevel=2)
-    Gtk.Action.set_tool_item_type = classmethod(set_tool_item_type)
+    _patch(Gtk.Action, "set_tool_item_type", classmethod(set_tool_item_type))
 
     # Alignment
 
@@ -261,7 +302,7 @@ def enable_gtk(version='3.0'):
             self.props.xscale = xscale
             self.props.yscale = yscale
 
-    Gtk.Alignment = Alignment
+    _patch(Gtk, "Alignment", Alignment)
 
     # Box
 
@@ -269,13 +310,13 @@ def enable_gtk(version='3.0'):
 
     def pack_end(self, child, expand=True, fill=True, padding=0):
         orig_pack_end(self, child, expand, fill, padding)
-    Gtk.Box.pack_end = pack_end
+    _patch(Gtk.Box, "pack_end", pack_end)
 
     orig_pack_start = Gtk.Box.pack_start
 
     def pack_start(self, child, expand=True, fill=True, padding=0):
         orig_pack_start(self, child, expand, fill, padding)
-    Gtk.Box.pack_start = pack_start
+    _patch(Gtk.Box, "pack_start", pack_start)
 
     # TreeViewColumn
 
@@ -283,13 +324,13 @@ def enable_gtk(version='3.0'):
 
     def tree_view_column_pack_end(self, cell, expand=True):
         orig_tree_view_column_pack_end(self, cell, expand)
-    Gtk.TreeViewColumn.pack_end = tree_view_column_pack_end
+    _patch(Gtk.TreeViewColumn, "pack_end", tree_view_column_pack_end)
 
     orig_tree_view_column_pack_start = Gtk.TreeViewColumn.pack_start
 
     def tree_view_column_pack_start(self, cell, expand=True):
         orig_tree_view_column_pack_start(self, cell, expand)
-    Gtk.TreeViewColumn.pack_start = tree_view_column_pack_start
+    _patch(Gtk.TreeViewColumn, "pack_start", tree_view_column_pack_start)
 
     # CellLayout
 
@@ -297,13 +338,13 @@ def enable_gtk(version='3.0'):
 
     def cell_pack_end(self, cell, expand=True):
         orig_cell_pack_end(self, cell, expand)
-    Gtk.CellLayout.pack_end = cell_pack_end
+    _patch(Gtk.CellLayout, "pack_end", cell_pack_end)
 
     orig_cell_pack_start = Gtk.CellLayout.pack_start
 
     def cell_pack_start(self, cell, expand=True):
         orig_cell_pack_start(self, cell, expand)
-    Gtk.CellLayout.pack_start = cell_pack_start
+    _patch(Gtk.CellLayout, "pack_start", cell_pack_start)
 
     orig_set_cell_data_func = Gtk.CellLayout.set_cell_data_func
 
@@ -313,13 +354,13 @@ def enable_gtk(version='3.0'):
                 args = args[:-1]
             return func(*args)
         orig_set_cell_data_func(self, cell, callback, user_data)
-    Gtk.CellLayout.set_cell_data_func = set_cell_data_func
+    _patch(Gtk.CellLayout, "set_cell_data_func", set_cell_data_func)
 
     # CellRenderer
 
     class GenericCellRenderer(Gtk.CellRenderer):
         pass
-    Gtk.GenericCellRenderer = GenericCellRenderer
+    _patch(Gtk, "GenericCellRenderer", GenericCellRenderer)
 
     # ComboBox
 
@@ -331,7 +372,7 @@ def enable_gtk(version='3.0'):
                 args = args[:-1]
             return func(*args)
         orig_combo_row_separator_func(self, callback, user_data)
-    Gtk.ComboBox.set_row_separator_func = combo_row_separator_func
+    _patch(Gtk.ComboBox, "set_row_separator_func", combo_row_separator_func)
 
     # ComboBoxEntry
 
@@ -344,22 +385,22 @@ def enable_gtk(version='3.0'):
 
         def get_text_column(self):
             return self.get_entry_text_column()
-    Gtk.ComboBoxEntry = ComboBoxEntry
+    _patch(Gtk, "ComboBoxEntry", ComboBoxEntry)
 
     def combo_box_entry_new():
         return Gtk.ComboBoxEntry()
-    Gtk.combo_box_entry_new = combo_box_entry_new
+    _patch(Gtk, "combo_box_entry_new", combo_box_entry_new)
 
     def combo_box_entry_new_with_model(model):
         return Gtk.ComboBoxEntry(model=model)
-    Gtk.combo_box_entry_new_with_model = combo_box_entry_new_with_model
+    _patch(Gtk, "combo_box_entry_new_with_model", combo_box_entry_new_with_model)
 
     # Container
 
     def install_child_property(container, flag, pspec):
         warnings.warn('install_child_property() is not supported',
                       gi.PyGIDeprecationWarning, stacklevel=2)
-    Gtk.Container.install_child_property = classmethod(install_child_property)
+    _patch(Gtk.Container, "install_child_property", classmethod(install_child_property))
 
     def new_text():
         combo = Gtk.ComboBox()
@@ -367,32 +408,32 @@ def enable_gtk(version='3.0'):
         combo.set_model(model)
         combo.set_entry_text_column(0)
         return combo
-    Gtk.combo_box_new_text = new_text
+    _patch(Gtk, "combo_box_new_text", new_text)
 
     def append_text(self, text):
         model = self.get_model()
         model.append([text])
-    Gtk.ComboBox.append_text = append_text
-    Gtk.expander_new_with_mnemonic = Gtk.Expander.new_with_mnemonic
-    Gtk.icon_theme_get_default = Gtk.IconTheme.get_default
-    Gtk.image_new_from_pixbuf = Gtk.Image.new_from_pixbuf
-    Gtk.image_new_from_stock = Gtk.Image.new_from_stock
-    Gtk.image_new_from_animation = Gtk.Image.new_from_animation
-    Gtk.image_new_from_icon_set = Gtk.Image.new_from_icon_set
-    Gtk.image_new_from_file = Gtk.Image.new_from_file
-    Gtk.settings_get_default = Gtk.Settings.get_default
-    Gtk.window_set_default_icon = Gtk.Window.set_default_icon
+    _patch(Gtk.ComboBox, "append_text", append_text)
+    _patch(Gtk, "expander_new_with_mnemonic", Gtk.Expander.new_with_mnemonic)
+    _patch(Gtk, "icon_theme_get_default", Gtk.IconTheme.get_default)
+    _patch(Gtk, "image_new_from_pixbuf", Gtk.Image.new_from_pixbuf)
+    _patch(Gtk, "image_new_from_stock", Gtk.Image.new_from_stock)
+    _patch(Gtk, "image_new_from_animation", Gtk.Image.new_from_animation)
+    _patch(Gtk, "image_new_from_icon_set", Gtk.Image.new_from_icon_set)
+    _patch(Gtk, "image_new_from_file", Gtk.Image.new_from_file)
+    _patch(Gtk, "settings_get_default", Gtk.Settings.get_default)
+    _patch(Gtk, "window_set_default_icon", Gtk.Window.set_default_icon)
     try:
-        Gtk.clipboard_get = Gtk.Clipboard.get
+        _patch(Gtk, "clipboard_get", Gtk.Clipboard.get)
     except AttributeError:
         pass
 
     # AccelGroup
-    Gtk.AccelGroup.connect_group = Gtk.AccelGroup.connect
+    _patch(Gtk.AccelGroup, "connect_group", Gtk.AccelGroup.connect)
 
     # StatusIcon
-    Gtk.status_icon_position_menu = Gtk.StatusIcon.position_menu
-    Gtk.StatusIcon.set_tooltip = Gtk.StatusIcon.set_tooltip_text
+    _patch(Gtk, "status_icon_position_menu", Gtk.StatusIcon.position_menu)
+    _patch(Gtk.StatusIcon, "set_tooltip", Gtk.StatusIcon.set_tooltip_text)
 
     # Scale
 
@@ -402,20 +443,20 @@ def enable_gtk(version='3.0'):
     class HScale(orig_HScale):
         def __init__(self, adjustment=None):
             orig_HScale.__init__(self, adjustment=adjustment)
-    Gtk.HScale = HScale
+    _patch(Gtk, "HScale", HScale)
 
     class VScale(orig_VScale):
         def __init__(self, adjustment=None):
             orig_VScale.__init__(self, adjustment=adjustment)
-    Gtk.VScale = VScale
+    _patch(Gtk, "VScale", VScale)
 
-    Gtk.stock_add = lambda items: None
+    _patch(Gtk, "stock_add", lambda items: None)
 
     # Widget
 
-    Gtk.Widget.window = property(fget=Gtk.Widget.get_window)
+    _patch(Gtk.Widget, "window", property(fget=Gtk.Widget.get_window))
 
-    Gtk.widget_get_default_direction = Gtk.Widget.get_default_direction
+    _patch(Gtk, "widget_get_default_direction", Gtk.Widget.get_default_direction)
     orig_size_request = Gtk.Widget.size_request
 
     def size_request(widget):
@@ -425,8 +466,8 @@ def enable_gtk(version='3.0'):
                 self.width = req.width
                 UserList.__init__(self, [self.width, self.height])
         return SizeRequest(orig_size_request(widget))
-    Gtk.Widget.size_request = size_request
-    Gtk.Widget.hide_all = Gtk.Widget.hide
+    _patch(Gtk.Widget, "size_request", size_request)
+    _patch(Gtk.Widget, "hide_all", Gtk.Widget.hide)
 
     class BaseGetter(object):
         def __init__(self, context):
@@ -447,7 +488,7 @@ def enable_gtk(version='3.0'):
     class StyleDescriptor(object):
         def __get__(self, instance, class_):
             return Styles(instance)
-    Gtk.Widget.style = StyleDescriptor()
+    _patch(Gtk.Widget, "style", StyleDescriptor())
 
     # TextView
 
@@ -457,7 +498,7 @@ def enable_gtk(version='3.0'):
                                  use_align=False, xalign=0.5, yalign=0.5):
         return orig_text_view_scroll_to_mark(self, mark, within_margin,
                                              use_align, xalign, yalign)
-    Gtk.TextView.scroll_to_mark = text_view_scroll_to_mark
+    _patch(Gtk.TextView, "scroll_to_mark", text_view_scroll_to_mark)
 
     # Window
 
@@ -501,16 +542,16 @@ def enable_gtk(version='3.0'):
 
         return orig_set_geometry_hints(self, geometry_widget, geometry, geom_mask)
 
-    Gtk.Window.set_geometry_hints = set_geometry_hints
-    Gtk.window_list_toplevels = Gtk.Window.list_toplevels
-    Gtk.window_set_default_icon_name = Gtk.Window.set_default_icon_name
+    _patch(Gtk.Window, "set_geometry_hints", set_geometry_hints)
+    _patch(Gtk, "window_list_toplevels", Gtk.Window.list_toplevels)
+    _patch(Gtk, "window_set_default_icon_name", Gtk.Window.set_default_icon_name)
 
     # gtk.unixprint
 
     class UnixPrint(object):
         pass
     unixprint = UnixPrint()
-    sys.modules['gtkunixprint'] = unixprint
+    _patch_module('gtkunixprint', unixprint)
 
     # gtk.keysyms
 
@@ -518,11 +559,11 @@ def enable_gtk(version='3.0'):
         warnings.simplefilter('ignore', category=RuntimeWarning)
         from gi.overrides import keysyms
 
-    sys.modules['gtk.keysyms'] = keysyms
-    Gtk.keysyms = keysyms
+    _patch_module('gtk.keysyms', keysyms)
+    _patch(Gtk, "keysyms", keysyms)
 
     from . import generictreemodel
-    Gtk.GenericTreeModel = generictreemodel.GenericTreeModel
+    _patch(Gtk, "GenericTreeModel", generictreemodel.GenericTreeModel)
 
 
 def enable_vte():
@@ -531,7 +572,7 @@ def enable_vte():
 
     gi.require_version('Vte', '0.0')
     from gi.repository import Vte
-    sys.modules['vte'] = Vte
+    _patch_module('vte', Vte)
 
 
 def enable_poppler():
@@ -540,8 +581,9 @@ def enable_poppler():
 
     gi.require_version('Poppler', '0.18')
     from gi.repository import Poppler
-    sys.modules['poppler'] = Poppler
-    Poppler.pypoppler_version = (1, 0, 0)
+    _patch_module('poppler', Poppler)
+
+    _patch(Poppler, "pypoppler_version", (1, 0, 0))
 
 
 def enable_webkit(version='1.0'):
@@ -550,8 +592,9 @@ def enable_webkit(version='1.0'):
 
     gi.require_version('WebKit', version)
     from gi.repository import WebKit
-    sys.modules['webkit'] = WebKit
-    WebKit.WebView.get_web_inspector = WebKit.WebView.get_inspector
+    _patch_module('webkit', WebKit)
+
+    _patch(WebKit.WebView, "get_web_inspector", WebKit.WebView.get_inspector)
 
 
 def enable_gudev():
@@ -560,7 +603,7 @@ def enable_gudev():
 
     gi.require_version('GUdev', '1.0')
     from gi.repository import GUdev
-    sys.modules['gudev'] = GUdev
+    _patch_module('gudev', GUdev)
 
 
 def enable_gst():
@@ -569,40 +612,41 @@ def enable_gst():
 
     gi.require_version('Gst', '0.10')
     from gi.repository import Gst
-    sys.modules['gst'] = Gst
+    _patch_module('gst', Gst)
     _install_enums(Gst)
-    Gst.registry_get_default = Gst.Registry.get_default
-    Gst.element_register = Gst.Element.register
-    Gst.element_factory_make = Gst.ElementFactory.make
-    Gst.caps_new_any = Gst.Caps.new_any
-    Gst.get_pygst_version = lambda: (0, 10, 19)
-    Gst.get_gst_version = lambda: (0, 10, 40)
+
+    _patch(Gst, "registry_get_default", Gst.Registry.get_default)
+    _patch(Gst, "element_register", Gst.Element.register)
+    _patch(Gst, "element_factory_make", Gst.ElementFactory.make)
+    _patch(Gst, "caps_new_any", Gst.Caps.new_any)
+    _patch(Gst, "get_pygst_version", lambda: (0, 10, 19))
+    _patch(Gst, "get_gst_version", lambda: (0, 10, 40))
 
     from gi.repository import GstInterfaces
-    sys.modules['gst.interfaces'] = GstInterfaces
+    _patch_module('gst.interfaces', GstInterfaces)
     _install_enums(GstInterfaces)
 
     from gi.repository import GstAudio
-    sys.modules['gst.audio'] = GstAudio
+    _patch_module('gst.audio', GstAudio)
     _install_enums(GstAudio)
 
     from gi.repository import GstVideo
-    sys.modules['gst.video'] = GstVideo
+    _patch_module('gst.video', GstVideo)
     _install_enums(GstVideo)
 
     from gi.repository import GstBase
-    sys.modules['gst.base'] = GstBase
+    _patch_module('gst.base', GstBase)
     _install_enums(GstBase)
 
-    Gst.BaseTransform = GstBase.BaseTransform
-    Gst.BaseSink = GstBase.BaseSink
+    _patch(Gst, "BaseTransform", GstBase.BaseTransform)
+    _patch(Gst, "BaseSink", GstBase.BaseSink)
 
     from gi.repository import GstController
-    sys.modules['gst.controller'] = GstController
+    _patch_module('gst.controller', GstController)
     _install_enums(GstController, dest=Gst)
 
     from gi.repository import GstPbutils
-    sys.modules['gst.pbutils'] = GstPbutils
+    _patch_module('gst.pbutils', GstPbutils)
     _install_enums(GstPbutils)
 
 
@@ -612,10 +656,11 @@ def enable_goocanvas():
 
     gi.require_version('GooCanvas', '2.0')
     from gi.repository import GooCanvas
-    sys.modules['goocanvas'] = GooCanvas
+    _patch_module('goocanvas', GooCanvas)
     _install_enums(GooCanvas, strip='GOO_CANVAS_')
-    GooCanvas.ItemSimple = GooCanvas.CanvasItemSimple
-    GooCanvas.Item = GooCanvas.CanvasItem
-    GooCanvas.Image = GooCanvas.CanvasImage
-    GooCanvas.Group = GooCanvas.CanvasGroup
-    GooCanvas.Rect = GooCanvas.CanvasRect
+
+    _patch(GooCanvas, "ItemSimple", GooCanvas.CanvasItemSimple)
+    _patch(GooCanvas, "Item", GooCanvas.CanvasItem)
+    _patch(GooCanvas, "Image", GooCanvas.CanvasImage)
+    _patch(GooCanvas, "Group", GooCanvas.CanvasGroup)
+    _patch(GooCanvas, "Rect", GooCanvas.CanvasRect)
diff --git a/setup.py b/setup.py
index c76bc9f2..fd781092 100755
--- a/setup.py
+++ b/setup.py
@@ -458,13 +458,6 @@ class test(Command):
             os.path.join(tests_dir, "runtests.py"),
         ], env=env)
 
-        if not env.get("TEST_NAMES"):
-            env["TEST_NAMES"] = "compat_test_pygtk"
-            subprocess.check_call([
-                sys.executable,
-                os.path.join(tests_dir, "runtests.py"),
-            ], env=env)
-
 
 class quality(Command):
     description = "run code quality tests"
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 6c0cedf6..4a9ec2aa 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -166,9 +166,7 @@ RUN_TESTS_ENV_VARS= \
 # pygtkcompat tests need to be run in a separate process as they
 # clobber global name space
 check-local: $(target_libraries) $(test_typelibs) gschemas.compiled
-       $(RUN_TESTS_ENV_VARS) $(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py; rc=$$?; \
-       [ "$$rc" -ne 0 ] || [ -n "$$TEST_NAMES" ] || { TEST_NAMES=compat_test_pygtk $(RUN_TESTS_ENV_VARS)  
$(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py; rc=$$?; }; \
-       exit $$rc
+       $(RUN_TESTS_ENV_VARS) $(EXTRA_ENV) $(EXEC_NAME) $(PYTHON) -Wd $(srcdir)/runtests.py;
 
 check.gdb:
        EXEC_NAME="gdb --args" $(MAKE) check
diff --git a/tests/runtests.py b/tests/runtests.py
index 457553fb..eeeb9b27 100755
--- a/tests/runtests.py
+++ b/tests/runtests.py
@@ -121,7 +121,7 @@ elif len(sys.argv) > 1:
         names.append(filename.replace('.py', ''))
 else:
     names = []
-    for filename in glob.iglob(os.path.join(mydir, 'test_*.py')):
+    for filename in sorted(glob.iglob(os.path.join(mydir, 'test_*.py'))):
         names.append(os.path.basename(filename)[:-3])
 
 
diff --git a/tests/compat_test_pygtk.py b/tests/test_pygtkcompat.py
similarity index 78%
rename from tests/compat_test_pygtk.py
rename to tests/test_pygtkcompat.py
index 65522567..3580ca4c 100644
--- a/tests/compat_test_pygtk.py
+++ b/tests/test_pygtkcompat.py
@@ -4,32 +4,40 @@
 import unittest
 import base64
 
+import pygtkcompat
+from pygtkcompat.pygtkcompat import _disable_all as disable_all
+
+from helper import capture_gi_deprecation_warnings, capture_glib_warnings
+
 try:
-    from gi.repository import Gtk
-    from gi.repository import Pango
-    from gi.repository import Atk
-    from gi.repository import Gdk
-    (Atk, Gtk, Pango)  # pyflakes
-
-    import pygtkcompat
-
-    pygtkcompat.enable()
-    pygtkcompat.enable_gtk(version=Gtk._version)
-
-    import atk
-    import pango
-    import pangocairo
-    import gtk
-    import gtk.gdk
-except (ValueError, ImportError):
+    from gi.repository import Gtk, Gdk
+except ImportError:
     Gtk = None
+else:
+    if Gtk._version != "3.0":
+        Gtk = None
 
-from helper import capture_gi_deprecation_warnings, capture_glib_warnings
+
+class TestGlibCompat(unittest.TestCase):
+
+    def setUp(self):
+        pygtkcompat.enable()
+
+    def tearDown(self):
+        disable_all()
+
+    def test_import(self):
+        import glib
+        import gio
+        glib, gio
 
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestMultipleEnable(unittest.TestCase):
 
+    def tearDown(self):
+        disable_all()
+
     def test_main(self):
         pygtkcompat.enable()
         pygtkcompat.enable()
@@ -37,6 +45,7 @@ class TestMultipleEnable(unittest.TestCase):
     def test_gtk(self):
         pygtkcompat.enable_gtk("3.0")
         pygtkcompat.enable_gtk("3.0")
+        import gtk
 
         # https://bugzilla.gnome.org/show_bug.cgi?id=759009
         w = gtk.Window()
@@ -44,39 +53,77 @@ class TestMultipleEnable(unittest.TestCase):
         self.assertEqual(len(w.window.get_origin()), 2)
         w.destroy()
 
+    def test_gtk_no_4(self):
+        self.assertRaises(ValueError, pygtkcompat.enable_gtk, version='4.0')
+
     def test_gtk_version_conflict(self):
+        pygtkcompat.enable_gtk("3.0")
         self.assertRaises(ValueError, pygtkcompat.enable_gtk, version='2.0')
 
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestATKCompat(unittest.TestCase):
+
+    def setUp(self):
+        pygtkcompat.enable_gtk("3.0")
+
+    def tearDown(self):
+        disable_all()
+
     def test_object(self):
+        import atk
         self.assertTrue(hasattr(atk, 'Object'))
 
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestPangoCompat(unittest.TestCase):
+
+    def setUp(self):
+        pygtkcompat.enable_gtk("3.0")
+
+    def tearDown(self):
+        disable_all()
+
     def test_layout(self):
+        import pango
         self.assertTrue(hasattr(pango, 'Layout'))
 
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestPangoCairoCompat(unittest.TestCase):
+
+    def setUp(self):
+        pygtkcompat.enable_gtk("3.0")
+
+    def tearDown(self):
+        disable_all()
+
     def test_error_underline_path(self):
+        import pangocairo
         self.assertTrue(hasattr(pangocairo, 'error_underline_path'))
 
 
 @unittest.skipUnless(Gtk, 'Gtk not available')
 class TestGTKCompat(unittest.TestCase):
+
+    def setUp(self):
+        pygtkcompat.enable_gtk("3.0")
+
+    def tearDown(self):
+        disable_all()
+
     def test_buttons(self):
-        self.assertEqual(Gdk._2BUTTON_PRESS, 5)
-        self.assertEqual(Gdk.BUTTON_PRESS, 4)
+        import gtk.gdk
+        self.assertEqual(gtk.gdk._2BUTTON_PRESS, 5)
+        self.assertEqual(gtk.gdk.BUTTON_PRESS, 4)
 
     def test_enums(self):
+        import gtk
         self.assertEqual(gtk.WINDOW_TOPLEVEL, Gtk.WindowType.TOPLEVEL)
         self.assertEqual(gtk.PACK_START, Gtk.PackType.START)
 
     def test_flags(self):
+        import gtk
         self.assertEqual(gtk.EXPAND, Gtk.AttachOptions.EXPAND)
         self.assertEqual(gtk.gdk.SHIFT_MASK, Gdk.ModifierType.SHIFT_MASK)
 
@@ -86,6 +133,7 @@ class TestGTKCompat(unittest.TestCase):
         self.assertTrue(gtk.keysyms._0, Gdk.KEY_0)
 
     def test_style(self):
+        import gtk
         widget = gtk.Button()
         with capture_gi_deprecation_warnings():
             widget.get_style_context().set_state(gtk.STATE_NORMAL)
@@ -93,6 +141,7 @@ class TestGTKCompat(unittest.TestCase):
                                        gtk.gdk.Color))
 
     def test_alignment(self):
+        import gtk
         # Creation of pygtk.Alignment causes hard warnings, ignore this in testing.
         with capture_glib_warnings(allow_warnings=True):
             a = gtk.Alignment()
@@ -103,6 +152,7 @@ class TestGTKCompat(unittest.TestCase):
         self.assertEqual(a.props.yscale, 0.0)
 
     def test_box(self):
+        import gtk
         box = gtk.Box()
         child = gtk.Button()
 
@@ -122,6 +172,7 @@ class TestGTKCompat(unittest.TestCase):
         self.assertEqual(pack_type, gtk.PACK_END)
 
     def test_combobox_entry(self):
+        import gtk
         liststore = gtk.ListStore(int, str)
         liststore.append((1, 'One'))
         liststore.append((2, 'Two'))
@@ -146,14 +197,17 @@ class TestGTKCompat(unittest.TestCase):
         self.assertEqual(combo.get_child().get_text(), 'One')
 
     def test_size_request(self):
+        import gtk
         box = gtk.Box()
         with capture_gi_deprecation_warnings():
             self.assertEqual(box.size_request(), [0, 0])
 
     def test_pixbuf(self):
+        import gtk.gdk
         gtk.gdk.Pixbuf()
 
     def test_pixbuf_loader(self):
+        import gtk.gdk
         # load a 1x1 pixel PNG from memory
         data = base64.b64decode('iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP4n8Dw'
                                 'HwAGIAJf85Z3XgAAAABJRU5ErkJggg==')
@@ -166,6 +220,7 @@ class TestGTKCompat(unittest.TestCase):
         self.assertEqual(pixbuf.get_height(), 1)
 
     def test_pixbuf_formats(self):
+        import gtk.gdk
         formats = gtk.gdk.pixbuf_get_formats()
         self.assertEqual(type(formats[0]), dict)
         self.assertTrue('name' in formats[0])
@@ -174,6 +229,7 @@ class TestGTKCompat(unittest.TestCase):
         self.assertEqual(type(formats[0]['extensions']), list)
 
     def test_gdk_window(self):
+        import gtk
         w = gtk.Window()
         w.realize()
         origin = w.get_window().get_origin()


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