[gnome-tweak-tool] Port GNOME Tweak Tool to Python 3



commit 4216c7ac8435194a4e63560ce975b49acc784f21
Author: Ikey Doherty <michael i doherty intel com>
Date:   Fri Apr 14 16:55:03 2017 +0100

    Port GNOME Tweak Tool to Python 3
    
    This change modernises GTT by requiring Python 3 only. Portions of this
    change were made using the 2to3 tool, whereas others are manual ports to
    ensure use of new Python approaches.
    
    Additionally, we fix a startup crash when GNOME Shell isn't running, i.e.
    GNOME Tweak Tool has been used in a GNOME based environment but not GNOME
    Shell itself.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=781321

 configure.ac                                  |    2 +-
 gnome-tweak-tool                              |    2 +-
 gtweak/app.py                                 |    2 +-
 gtweak/egowrapper.py                          |    8 +++---
 gtweak/gsettings.py                           |    4 +-
 gtweak/gshellwrapper.py                       |    8 +++---
 gtweak/gtksettings.py                         |    8 ++----
 gtweak/tweakmodel.py                          |    2 +-
 gtweak/tweaks/tweak_group_interface.py        |    4 +-
 gtweak/tweaks/tweak_group_shell_extensions.py |    9 ++++---
 gtweak/tweaks/tweak_group_startup.py          |    4 +-
 gtweak/tweaks/tweak_group_test.py             |    2 +-
 gtweak/tweaks/tweak_group_windows.py          |   18 +++------------
 gtweak/tweaks/tweak_group_workspaces.py       |    2 +-
 gtweak/tweaks/tweak_group_xkb.py              |   29 +++++++++++++++++++++---
 gtweak/tweaks/tweak_wacom.py                  |    6 ++--
 gtweak/tweakview.py                           |    2 +-
 gtweak/utils.py                               |    5 ++-
 gtweak/widgets.py                             |    4 +-
 19 files changed, 66 insertions(+), 55 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index db00816..86328f1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -4,7 +4,7 @@ AM_INIT_AUTOMAKE([foreign tar-ustar dist-xz no-dist-gzip])
 
 AC_CONFIG_MACRO_DIR([m4])
 
-AM_PATH_PYTHON([2.6])
+AM_PATH_PYTHON([3])
 GLIB_GSETTINGS
 
 DESKTOP_SCHEMAS_REQUIRED_VERSION=3.23.3
diff --git a/gnome-tweak-tool b/gnome-tweak-tool
index 017fab0..80010e7 100755
--- a/gnome-tweak-tool
+++ b/gnome-tweak-tool
@@ -1,4 +1,4 @@
-#!/usr/bin/python2
+#!/usr/bin/python3
 
 # This program is free software: you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
diff --git a/gtweak/app.py b/gtweak/app.py
index 7e4ecc5..8fd1773 100644
--- a/gtweak/app.py
+++ b/gtweak/app.py
@@ -85,7 +85,7 @@ class GnomeTweakTool(Gtk.Application):
         dialog.destroy()
             
     def help_cb(self, action, parameter):
-        print "This does nothing. It is only a demonstration."
+        print("This does nothing. It is only a demonstration.")
 
     def disable_cb(self, action, parameter):
         ds = DisableExtension()
diff --git a/gtweak/egowrapper.py b/gtweak/egowrapper.py
index 9d105d2..a13084a 100644
--- a/gtweak/egowrapper.py
+++ b/gtweak/egowrapper.py
@@ -43,7 +43,7 @@ class ExtensionsDotGnomeDotOrg(GObject.GObject):
         if msg.status_code == 200:
             #server returns a list of extensions which may contain duplicates, dont know
             resp = json.loads(msg.response_body.data)
-            print resp
+            print(resp)
             for e in resp["extensions"]:
                 self._extensions[e["uuid"]] = e
             self.emit("got-extensions", self._extensions)
@@ -75,7 +75,7 @@ class ExtensionsDotGnomeDotOrg(GObject.GObject):
 
     def query_extension_info(self, extension_uuid):
         if extension_uuid in self._extensions:
-            print "CACHED"
+            print("CACHED")
             self.emit("got-extension-info", self._extensions[extension_uuid])
             return
 
@@ -96,8 +96,8 @@ if __name__ == "__main__":
     from gi.repository import Gtk, GLib
 
     def _got_ext(ego, extensions):
-        print "="*80
-        pprint.pprint(extensions.values())
+        print("="*80)
+        pprint.pprint(list(extensions.values()))
 
     def _got_ext_info(ego, extension):
         pprint.pprint(extension)
diff --git a/gtweak/gsettings.py b/gtweak/gsettings.py
index 8815131..3bcadc7 100644
--- a/gtweak/gsettings.py
+++ b/gtweak/gsettings.py
@@ -146,7 +146,7 @@ class GSettingsSetting(Gio.Settings):
             self.connect("changed", self._on_changed)
 
     def _on_changed(self, settings, key_name):
-        print "Change: %s %s -> %s" % (self.props.schema, key_name, self[key_name])
+        print("Change: %s %s -> %s" % (self.props.schema, key_name, self[key_name]))
 
     def _setting_check_is_list(self, key):
         variant = Gio.Settings.get_value(self, key)
@@ -193,7 +193,7 @@ if __name__ == "__main__":
 
     key = "draw-background"
     s = GSettingsSetting("org.gnome.desktop.background")
-    print s.schema_get_summary(key), s.schema_get_description(key)
+    print(s.schema_get_summary(key), s.schema_get_description(key))
 
     key = "disabled-extensions"
     s = GSettingsSetting("org.gnome.shell")
diff --git a/gtweak/gshellwrapper.py b/gtweak/gshellwrapper.py
index ca7e7c0..3f2d8b6 100644
--- a/gtweak/gshellwrapper.py
+++ b/gtweak/gshellwrapper.py
@@ -172,7 +172,7 @@ class GnomeShellFactory:
         try:
             proxy = _ShellProxy()
             settings = GSettingsSetting("org.gnome.shell")
-            v = map(int,proxy.version.split("."))
+            v = list(map(int,proxy.version.split(".")))
 
             if v >= [3,5,0]:
                 self.shell = GnomeShell36(proxy, settings)
@@ -198,7 +198,7 @@ if __name__ == "__main__":
     logging.basicConfig(format="%(levelname)-8s: %(message)s", level=logging.DEBUG)
 
     s = GnomeShellFactory().get_shell()
-    print "Shell Version: %s" % s.version
-    print s.list_extensions()
+    print("Shell Version: %s" % s.version)
+    print(s.list_extensions())
 
-    print s == GnomeShellFactory().get_shell()
+    print(s == GnomeShellFactory().get_shell())
diff --git a/gtweak/gtksettings.py b/gtweak/gtksettings.py
index b869233..d656b2e 100644
--- a/gtweak/gtksettings.py
+++ b/gtweak/gtksettings.py
@@ -16,7 +16,6 @@
 # along with gnome-tweak-tool.  If not, see <http://www.gnu.org/licenses/>.
 
 import os.path
-import errno
 import logging
 
 from gi.repository import GLib
@@ -57,14 +56,13 @@ class GtkSettingsManager:
 
         try:
             os.makedirs(os.path.dirname(self._path))
-        except OSError, e:
-            if e.errno is not errno.EEXIST:
-                raise
+        except FileExistsError:
+            pass
         except:
             raise
 
         try:
             data = keyfile.to_data()
-            GLib.file_set_contents(self._path, data[0])
+            GLib.file_set_contents(self._path, data[0].encode())
         except:
             raise
diff --git a/gtweak/tweakmodel.py b/gtweak/tweakmodel.py
index 750e108..f0e0e96 100644
--- a/gtweak/tweakmodel.py
+++ b/gtweak/tweakmodel.py
@@ -91,7 +91,7 @@ class TweakGroup(object):
 
 class TweakModel(Gtk.ListStore):
     (COLUMN_NAME,
-     COLUMN_TWEAK) = range(2)
+     COLUMN_TWEAK) = list(range(2))
 
     def __init__(self):
         super(TweakModel, self).__init__(str, object)
diff --git a/gtweak/tweaks/tweak_group_interface.py b/gtweak/tweaks/tweak_group_interface.py
index 16fda81..400b67a 100644
--- a/gtweak/tweaks/tweak_group_interface.py
+++ b/gtweak/tweaks/tweak_group_interface.py
@@ -135,13 +135,13 @@ class ShellThemeTweak(Gtk.Box, Tweak):
                         error = None
                     except:
                         logging.warning(
-                            "Could not find user-theme extension in %s" % ','.join(extensions.keys()),
+                            "Could not find user-theme extension in %s" % ','.join(list(extensions.keys())),
                             exc_info=True)
                         error = _("Shell user-theme extension incorrectly installed")
 
                 else:
                     error = _("Shell user-theme extension not enabled")
-            except Exception, e:
+            except Exception as e:
                 logging.warning("Could not list shell extensions", exc_info=True)
                 error = _("Could not list shell extensions")
 
diff --git a/gtweak/tweaks/tweak_group_shell_extensions.py b/gtweak/tweaks/tweak_group_shell_extensions.py
index 5045013..ee7cf03 100644
--- a/gtweak/tweaks/tweak_group_shell_extensions.py
+++ b/gtweak/tweaks/tweak_group_shell_extensions.py
@@ -184,7 +184,7 @@ class _ShellExtensionTweak(Gtk.ListBoxRow, Tweak):
 
     def error_handler(self, proxy_object, result, user_data):
         user_data.set_label(_("Error"))
-        print result
+        print(result)
 
     def add_update_button(self, uuid):
         updateButton = Gtk.Button(_("Update"))   
@@ -213,7 +213,7 @@ class ShellExtensionTweakGroup(ListBoxTweakGroup):
             ego = ExtensionsDotGnomeDotOrg(version)
             try:
                 #add a tweak for each installed extension
-                extensions = sorted(shell.list_extensions().values(), key=itemgetter("name"))
+                extensions = sorted(list(shell.list_extensions().values()), key=itemgetter("name"))
                 for extension in extensions:
                     try:
                         extension_widget = _ShellExtensionTweak(shell, extension, size_group=sg)
@@ -235,8 +235,9 @@ class ShellExtensionTweakGroup(ListBoxTweakGroup):
         self.props.valign = Gtk.Align.FILL
 
         self.titlebar_widget = Gtk.Switch(visible=True)
-        shell._settings.bind("disable-user-extensions", self.titlebar_widget,
-                             "active", Gio.SettingsBindFlags.INVERT_BOOLEAN)
+        if shell is not None:
+            shell._settings.bind("disable-user-extensions", self.titlebar_widget,
+                                 "active", Gio.SettingsBindFlags.INVERT_BOOLEAN)
 
         self.set_header_func(self._list_header_func, None)
         self.connect("row-activated", self._on_row_activated, None);
diff --git a/gtweak/tweaks/tweak_group_startup.py b/gtweak/tweaks/tweak_group_startup.py
index 7c7cf26..43bb127 100644
--- a/gtweak/tweaks/tweak_group_startup.py
+++ b/gtweak/tweaks/tweak_group_startup.py
@@ -15,7 +15,7 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with gnome-tweak-tool.  If not, see <http://www.gnu.org/licenses/>.
-from __future__ import print_function
+
 
 import os.path
 import subprocess
@@ -338,7 +338,7 @@ class AutostartListBoxTweakGroup(ListBoxTweakGroup):
                     str(os.getuid()),'-o','cmd'],
                     stdout=subprocess.PIPE)
         out = cmd.communicate()[0]
-        for l in out.split('\n'):
+        for l in out.decode('utf8').split('\n'):
             exe = l.split(' ')[0]
             if exe and exe[0] != '[': #kernel process
                 exes.append( os.path.basename(exe) )
diff --git a/gtweak/tweaks/tweak_group_test.py b/gtweak/tweaks/tweak_group_test.py
index 54d4afa..a3a4501 100644
--- a/gtweak/tweaks/tweak_group_test.py
+++ b/gtweak/tweaks/tweak_group_test.py
@@ -16,7 +16,7 @@
 # You should have received a copy of the GNU General Public License
 # along with gnome-tweak-tool.  If not, see <http://www.gnu.org/licenses/>.
 
-from __future__ import print_function
+
 
 from gi.repository import Gtk, Gdk
 
diff --git a/gtweak/tweaks/tweak_group_windows.py b/gtweak/tweaks/tweak_group_windows.py
index 689f3c0..f50040c 100644
--- a/gtweak/tweaks/tweak_group_windows.py
+++ b/gtweak/tweaks/tweak_group_windows.py
@@ -42,37 +42,27 @@ class ShowWindowButtons(GSettingsSwitchTweakValue):
 
         if "close" in right:
             rsplit = right.split(",")
+            rsplit = [x for x in rsplit if x in ['appmenu', 'close', 'maximize', 'minimize']]
 
             if v:
                 rsplit.append(self.value)
             else:
                 rsplit.remove(self.value)
 
-            def sort_buttons(x, y):
-                order = ["minimize", "maximize", "close"];
-                if x in order and y in order:
-                     return order.index(x) - order.index(y)
-                else:
-                    return 0
-            rsplit.sort(cmp=sort_buttons)
+            rsplit.sort(key=lambda x: ["appmenu", "minimize", "maximize", "close"].index(x))
 
             self.settings.set_string(self.key_name, left + colon + ",".join(rsplit))
 
         else:
             rsplit = left.split(",")
+            rsplit = [x for x in rsplit if x in ['appmenu', 'close', 'maximize', 'minimize']]
 
             if v:
                 rsplit.append(self.value)
             else:
                 rsplit.remove(self.value)
 
-            def sort_buttons(x, y):
-                order = ["close", "maximize", "minimize"];
-                if x in order and y in order:
-                     return order.index(x) - order.index(y)
-                else:
-                    return 0
-            rsplit.sort(cmp=sort_buttons)
+            rsplit.sort(key=lambda x: ["appmenu", "close", "maximize", "minimize"].index(x))
 
             self.settings.set_string(self.key_name, ",".join(rsplit) + colon + right)
 
diff --git a/gtweak/tweaks/tweak_group_workspaces.py b/gtweak/tweaks/tweak_group_workspaces.py
index 826283e..3f5793b 100644
--- a/gtweak/tweaks/tweak_group_workspaces.py
+++ b/gtweak/tweaks/tweak_group_workspaces.py
@@ -36,7 +36,7 @@ class StaticWorkspaceTweak(Gtk.Box, _GSettingsTweak):
         Gtk.Box.__init__(self, orientation=Gtk.Orientation.HORIZONTAL)
         _GSettingsTweak.__init__(self, name, "org.gnome.mutter", "dynamic-workspaces", **options)
 
-        default = self.STATUS.keys()[self.STATUS.values().index(self.settings[self.key_name])]
+        default = list(self.STATUS.keys())[list(self.STATUS.values()).index(self.settings[self.key_name])]
         key_options = [("dynamic", _("Dynamic")), ("static", _("Static"))]
 
         self.combo = build_combo_box_text(default, *key_options)
diff --git a/gtweak/tweaks/tweak_group_xkb.py b/gtweak/tweaks/tweak_group_xkb.py
index d270c65..51bcdef 100644
--- a/gtweak/tweaks/tweak_group_xkb.py
+++ b/gtweak/tweaks/tweak_group_xkb.py
@@ -59,14 +59,35 @@ class _XkbOption(Gtk.Expander, Tweak):
             model_values.append((option_id, desc))
             self._possible_values.append(option_id)
 
-        def values_cmp((av, ad), (bv, bd)):
+        def values_cmp_py3_wrap(f):
+            ''' https://docs.python.org/3/howto/sorting.html#the-old-way-using-the-cmp-parameter '''
+            class C:
+                def __init__(self, obj, *args):
+                    self.obj = obj
+                def __lt__(self, other):
+                    return f(self.obj, other.obj) < 0
+                def __gt__(self, other):
+                    return f(self.obj, other.obj) > 0
+                def __eq__(self, other):
+                    return f(self.obj, other.obj) == 0
+                def __le__(self, other):
+                    return f(self.obj, other.obj) <= 0
+                def __ge__(self, other):
+                    return f(self.obj, other.obj) >= 0
+                def __ne__(self, other):
+                    return f(self.obj, other.obj) != 0
+            return C
+
+        def values_cmp(xxx_todo_changeme, xxx_todo_changeme1):
+            (av, ad) = xxx_todo_changeme
+            (bv, bd) = xxx_todo_changeme1
             if not av:
                 return -1
             elif not bv:
                 return 1
             else:
-                return cmp(ad, bd)
-        model_values.sort(cmp=values_cmp)
+                return (ad > bd) - (ad < bd)
+        model_values.sort(key=values_cmp_py3_wrap(values_cmp))
 
         self._widgets = dict()
         for (val, name) in model_values:
@@ -112,7 +133,7 @@ class _XkbOption(Gtk.Expander, Tweak):
                 if w:
                     _set_active(w, True)
         else:
-            for w in self._widgets.values():
+            for w in list(self._widgets.values()):
                 if w._val in self._values:
                     _set_active(w, True)
                 else:
diff --git a/gtweak/tweaks/tweak_wacom.py b/gtweak/tweaks/tweak_wacom.py
index 72ac36e..af8934e 100644
--- a/gtweak/tweaks/tweak_wacom.py
+++ b/gtweak/tweaks/tweak_wacom.py
@@ -19,7 +19,7 @@
 from gtweak.tweakmodel import TweakGroup
 from gtweak.widgets import GSettingsSwitchTweak
 import subprocess
-import ConfigParser
+import configparser
 import io
 
 def N_(x): return x
@@ -101,10 +101,10 @@ class WacomConfigs(object):
                 match_id = config.get(DEVICE_SECTION, DEVICE_MATCH_LINE)
                 # Use a dict to discard possible repeated devices
                 configs_dict[match_id] = config
-        return configs_dict.values()
+        return list(configs_dict.values())
 
     def _text_to_config(self, text):
-        config = ConfigParser.RawConfigParser(allow_no_value=True)
+        config = configparser.RawConfigParser(allow_no_value=True)
         config.readfp(io.BytesIO(text))
         return config
 
diff --git a/gtweak/tweakview.py b/gtweak/tweakview.py
index b0633c8..6c22e51 100644
--- a/gtweak/tweakview.py
+++ b/gtweak/tweakview.py
@@ -171,7 +171,7 @@ class Window(Gtk.ApplicationWindow):
             row.add(lbl)
             return row
 
-        groups = self._model._tweak_group_names.keys()
+        groups = list(self._model._tweak_group_names.keys())
         groups = sorted(groups)
 
         for g in groups:
diff --git a/gtweak/utils.py b/gtweak/utils.py
index 39f8833..607570b 100644
--- a/gtweak/utils.py
+++ b/gtweak/utils.py
@@ -111,7 +111,8 @@ def extract_zip_file(z, members_path, dest):
 def execute_subprocess(cmd_then_args, block=True):
     p = subprocess.Popen(
             cmd_then_args,
-            stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
+            stdin=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True,
+            universal_newlines=True)
     if block:
         stdout, stderr = p.communicate()
         return stdout, stderr, p.returncode
@@ -265,7 +266,7 @@ class XSettingsOverrides:
 
     def _dup_variant_as_dict(self):
         items = {}
-        for k in self._variant.keys():
+        for k in list(self._variant.keys()):
             try:
                 #variant override doesnt support .items()
                 v = self._variant[k]
diff --git a/gtweak/widgets.py b/gtweak/widgets.py
index b3c43c7..8c8bd7c 100644
--- a/gtweak/widgets.py
+++ b/gtweak/widgets.py
@@ -144,7 +144,7 @@ def adjust_schema_for_overrides(originalSchema, key, options):
         if (key in GSettingsSetting(overridesSchema, schema_filename=overridesFile).list_keys()):
             options['schema_filename'] = overridesFile
             return overridesSchema
-    except GSettingsMissingError, e:
+    except GSettingsMissingError as e:
         logging.info("GSetting missing %s" % (e.message))
 
     return originalSchema
@@ -164,7 +164,7 @@ class _GSettingsTweak(Tweak):
                 name,
                 options.get("description",self.settings.schema_get_description(key_name)),
                 **options)
-        except GSettingsMissingError, e:
+        except GSettingsMissingError as e:
             self.settings = GSettingsFakeSetting()
             Tweak.__init__(self,"","")
             self.loaded = False


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