[pygobject] [gi] python 3 fixes



commit 6ff357839feb39930a5f3175de3d0ed35f24d3f4
Author: John (J5) Palmieri <johnp redhat com>
Date:   Wed Jan 26 15:17:03 2011 -0500

    [gi] python 3 fixes
    
    Patches need to work in Python 3 - here are some of the issues I fixed up.
    Patch submitters should keep this in mind.  When I note to only use something
    in tests it means that there is a compat module that is only available to the
    tests.  Actuall code should either add the workaround to the top of their
    module or try not to have a distinction between things such as unicode and
    longs which no longer exist in Python 3
    
    * use range instead of xrange - loss of performance in Python 2 but Python 3 i
      treats range similarly to python 2's xrange
    * use dict.items() instead of dict.iteritems() - same as the xrange issue
    * callable does not exist in 3.x, use hasattr(obj, '__call__') or
    
          if sys.version_info > (3, 0):
              def callable(obj):
                  return hasattr(obj, '__call__')
    
    * using unicode in tests is tricky, you can't use u'' even in a versioned
      conditional as python3's parser chokes on it. Do this in tests (and only i
      in tests):
    
          from compathelper import _unicode
          unicode_string = _unicode('this is a unicode string')
    
    * exception caching changed in 2.7, instead of except Exception, e we now use
      except Exception as e.  Do this to be compatible with older versions:
    
          except Exception:
              etype, e = sys.exc_info()[:2]
    
    * Unbound methods with an im_func attribute no longer exits in 3.x.
      Unbound methods are now just functions so class.method in 3.x is
      equivalent to class.method.im_func in 2.x.  If you have to go this
      low level do this:
    
          func = class1.method
          if sys.version_info < (3,0):
              func = func.im_func
    
    * all numbers are long in 3.x so 42L is invalid in 3.x.  In tests (and
      only in tests) do this:
    
          from compathelper import _long
          l = _long(42)

 gi/overrides/GLib.py    |   16 ++++++++--------
 gi/types.py             |    5 ++++-
 tests/compathelper.py   |   19 +++++++++++++++++++
 tests/test_gdbus.py     |   12 ++++++++----
 tests/test_gi.py        |   19 ++++++++++++-------
 tests/test_overrides.py |    8 +++++---
 6 files changed, 56 insertions(+), 23 deletions(-)
---
diff --git a/gi/overrides/GLib.py b/gi/overrides/GLib.py
index dd85877..ac783be 100644
--- a/gi/overrides/GLib.py
+++ b/gi/overrides/GLib.py
@@ -102,7 +102,7 @@ class _VariantCreator(object):
             if not args or type(args[0]) != type(()):
                 raise (TypeError, 'expected tuple argument')
 
-            for i in xrange(len(args[0])):
+            for i in range(len(args[0])):
                 if format.startswith(')'):
                     raise (TypeError, 'too many arguments for tuple signature')
 
@@ -127,7 +127,7 @@ class _VariantCreator(object):
             builder.init(variant_type_from_string(element_type))
         else:
             builder.init(variant_type_from_string('a{?*}'))
-            for k, v in args[0].iteritems():
+            for k, v in args[0].items():
                 (key_v, rest_format, _) = self._create(format[2:], [k])
                 (val_v, rest_format, _) = self._create(rest_format, [v])
 
@@ -157,7 +157,7 @@ class _VariantCreator(object):
             builder.init(variant_type_from_string(element_type))
         else:
             builder.init(variant_type_from_string('a*'))
-            for i in xrange(len(args[0])):
+            for i in range(len(args[0])):
                 (v, rest_format, _) = self._create(format[1:], args[0][i:])
                 builder.add_value(v)
         if args is not None:
@@ -213,13 +213,13 @@ class Variant(GLib.Variant):
         # tuple
         if self.get_type_string().startswith('('):
             res = [self.get_child_value(i).unpack() 
-                    for i in xrange(self.n_children())]
+                    for i in range(self.n_children())]
             return tuple(res)
 
         # dictionary
         if self.get_type_string().startswith('a{'):
             res = {}
-            for i in xrange(self.n_children()):
+            for i in range(self.n_children()):
                 v = self.get_child_value(i)
                 res[v.get_child_value(0).unpack()] = v.get_child_value(1).unpack()
             return res
@@ -227,7 +227,7 @@ class Variant(GLib.Variant):
         # array
         if self.get_type_string().startswith('a'):
             return [self.get_child_value(i).unpack() 
-                    for i in xrange(self.n_children())]
+                    for i in range(self.n_children())]
 
         # variant (just unbox transparently)
         if self.get_type_string().startswith('v'):
@@ -257,7 +257,7 @@ class Variant(GLib.Variant):
                 # lookup_value() only works for string keys, which is certainly
                 # the common case; we have to do painful iteration for other
                 # key types
-                for i in xrange(self.n_children()):
+                for i in range(self.n_children()):
                     v = self.get_child_value(i)
                     if v.get_child_value(0).unpack() == key:
                         return v.get_child_value(1).unpack()
@@ -283,7 +283,7 @@ class Variant(GLib.Variant):
             return TypeError, 'GVariant type %s is not a dictionary' % self.get_type_string()
 
         res = []
-        for i in xrange(self.n_children()):
+        for i in range(self.n_children()):
             v = self.get_child_value(i)
             res.append(v.get_child_value(0).unpack())
         return res
diff --git a/gi/types.py b/gi/types.py
index b3a9d3d..a7a4569 100644
--- a/gi/types.py
+++ b/gi/types.py
@@ -34,6 +34,9 @@ from ._gi import \
     register_interface_info, \
     hook_up_vfunc_implementation
 
+if sys.version_info > (3, 0):
+    def callable(obj):
+        return hasattr(obj, '__call__')
 
 def Function(info):
 
@@ -104,7 +107,7 @@ class MetaClassHelper(object):
             setattr(cls, name, value)
 
     def _setup_vfuncs(cls):
-        for vfunc_name, py_vfunc in cls.__dict__.iteritems():
+        for vfunc_name, py_vfunc in cls.__dict__.items():
             if not vfunc_name.startswith("do_") or not callable(py_vfunc):
                 continue
 
diff --git a/tests/compathelper.py b/tests/compathelper.py
index 754285c..2465747 100644
--- a/tests/compathelper.py
+++ b/tests/compathelper.py
@@ -44,7 +44,26 @@ if sys.version_info >= (3, 0):
     '''
 
     _bytes = lambda s: s.encode()
+
+    '''
+    for tests that need to write to intefaces that take unicode in
+    python 2
+
+    python 3 strings are unicode encoded as UTF-8 so the unicode object 
+    doesn't exist
+
+    python 2 differs between a string an unicode string and you must specify
+    an encoding.  This macro will specify UTF-8 in python 2
+
+    any tests that need to use unicode should do this
+
+    from compathelper import _unicode
+    unicode_string = _unicode('this is a unicode string')
+    '''
+
+    _unicode = lambda s: str(s)
 else:
     _long = long
     _basestring = basestring
     _bytes = str
+    _unicode = lambda s: unicode(s, 'UTF-8')
diff --git a/tests/test_gdbus.py b/tests/test_gdbus.py
index 66df327..b5a253b 100644
--- a/tests/test_gdbus.py
+++ b/tests/test_gdbus.py
@@ -40,7 +40,8 @@ class TestGDBusClient(unittest.TestCase):
             self.dbus_proxy.call_sync('GetConnectionUnixProcessID', None,
                     Gio.DBusCallFlags.NO_AUTO_START, 500, None)
             self.fail('call with invalid arguments should raise an exception')
-        except Exception, e:
+        except Exception:
+            etype, e = sys.exc_info()[:2]
             self.assert_('InvalidArgs' in e.message)
 
         # error case: invalid argument
@@ -49,7 +50,8 @@ class TestGDBusClient(unittest.TestCase):
                     GLib.Variant('(s)', (' unknown',)),
                     Gio.DBusCallFlags.NO_AUTO_START, 500, None)
             self.fail('call with invalid arguments should raise an exception')
-        except Exception, e:
+        except Exception:
+            etype, e = sys.exc_info()[:2]
             self.assert_('NameHasNoOwner' in e.message)
 
         # error case: unknown method
@@ -57,7 +59,8 @@ class TestGDBusClient(unittest.TestCase):
             self.dbus_proxy.call_sync('UnknownMethod', None,
                     Gio.DBusCallFlags.NO_AUTO_START, 500, None)
             self.fail('call for unknown method should raise an exception')
-        except Exception, e:
+        except Exception:
+            etype, e = sys.exc_info()[:2]
             self.assert_('UnknownMethod' in e.message)
 
     def test_native_calls_async(self):
@@ -82,7 +85,8 @@ class TestGDBusClient(unittest.TestCase):
             try:
                 self.dbus_proxy.call_finish(result)
                 self.fail('call_finish() for unknown method should raise an exception')
-            except Exception, e:
+            except Exception:
+                etype, e = sys.exc_info()[:2]
                 self.assert_('UnknownMethod' in e.message)
             finally:
                 user_data['main_loop'].quit()
diff --git a/tests/test_gi.py b/tests/test_gi.py
index 19a7d46..3598e61 100644
--- a/tests/test_gi.py
+++ b/tests/test_gi.py
@@ -1456,9 +1456,13 @@ class TestPythonGObject(unittest.TestCase):
 
         # Here we check that accessing a vfunc from the subclass returns the same wrapper object,
         # meaning that multiple wrapper objects have not been created for the same vfunc.
-        self.assertTrue(GIMarshallingTests.Object.do_method_with_default_implementation.im_func is \
-                GIMarshallingTests.SubObject.do_method_with_default_implementation.im_func)
-
+        func1 = GIMarshallingTests.Object.do_method_with_default_implementation
+        func2 = GIMarshallingTests.SubObject.do_method_with_default_implementation
+        if sys.version_info < (3,0):
+            func1 = func1.im_func
+            func2 = func2.im_func
+            
+        self.assertTrue(func1 is func2)
 
 class TestMultiOutputArgs(unittest.TestCase):
 
@@ -1473,10 +1477,11 @@ class TestGErrorException(unittest.TestCase):
         self.assertRaises(GObject.GError, GIMarshallingTests.gerror)
         try:
             GIMarshallingTests.gerror()
-        except Exception, error:
-            self.assertEquals(error.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN)
-            self.assertEquals(error.code, GIMarshallingTests.CONSTANT_GERROR_CODE)
-            self.assertEquals(error.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE)
+        except Exception:
+            etype, e = sys.exc_info()[:2]
+            self.assertEquals(e.domain, GIMarshallingTests.CONSTANT_GERROR_DOMAIN)
+            self.assertEquals(e.code, GIMarshallingTests.CONSTANT_GERROR_CODE)
+            self.assertEquals(e.message, GIMarshallingTests.CONSTANT_GERROR_MESSAGE)
 
 
 # Interface
diff --git a/tests/test_overrides.py b/tests/test_overrides.py
index ec0fda4..25cea6a 100644
--- a/tests/test_overrides.py
+++ b/tests/test_overrides.py
@@ -6,6 +6,8 @@ import unittest
 import sys
 sys.path.insert(0, "../")
 
+from compathelper import _long, _unicode
+
 from gi.repository import GLib
 from gi.repository import GObject
 from gi.repository import Gdk
@@ -70,7 +72,7 @@ class TestGLib(unittest.TestCase):
         # nested tuples
         variant = GLib.Variant('((si)(ub))', (('hello', -1), (42, True)))
         self.assertEqual(variant.get_type_string(), '((si)(ub))')
-        self.assertEqual(variant.unpack(), (('hello', -1), (42L, True)))
+        self.assertEqual(variant.unpack(), (('hello', -1), (_long(42), True)))
 
         # dictionaries
 
@@ -684,7 +686,7 @@ class TestGtk(unittest.TestCase):
                                         test_pylist))
 
         i = 93
-        label = u'this is row #93'
+        label = _unicode('this is row #93')
         treeiter = list_store.append()
         list_store.set_value(treeiter, 0, i)
         list_store.set_value(treeiter, 1, label)
@@ -695,7 +697,7 @@ class TestGtk(unittest.TestCase):
 
         # test automatic unicode->str conversion
         i = 94
-        label = u'this is row #94'
+        label = _unicode('this is row #94')
         treeiter = list_store.append((i,
                                       label,
                                       TestGtk.TestClass(self, i, label),



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