Commit 4216c7ac authored by Ikey Doherty's avatar Ikey Doherty Committed by Florian Müllner

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
parent aeee5b7a
......@@ -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
......
#!/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
......
......@@ -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()
......
......@@ -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)
......
......@@ -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")
......
......@@ -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())
......@@ -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
......@@ -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)
......
......@@ -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")
......
......@@ -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);
......
......@@ -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) )
......
......@@ -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
......
......@@ -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)
......
......@@ -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)
......
......@@ -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:
......
......@@ -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
......
......@@ -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:
......
......@@ -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]
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment