diff --git a/linux/keyman-config/buildtools/build-langtags.py b/linux/keyman-config/buildtools/build-langtags.py
index d05e9746a6..ba7f8c5078 100755
--- a/linux/keyman-config/buildtools/build-langtags.py
+++ b/linux/keyman-config/buildtools/build-langtags.py
@@ -12,16 +12,19 @@ with open('../../../resources/standards-data/langtags/langtags.json') as file:
# The data comes from `resources/standards-data/langtag/langtags.json`.
class LangTagsMap():
+ @staticmethod
def lookupLangTags(language):
if language in LangTagsMap.__langTags:
return LangTagsMap.__langTags[language]
return None
+ @staticmethod
def lookupAllTags(language):
if language in LangTagsMap.__allTags:
return LangTagsMap.__allTags[language]
return None
+ @staticmethod
def translateISO6393ToBCP47(code):
if code in LangTagsMap.__map3To2:
return LangTagsMap.__map3To2[code]
@@ -41,8 +44,8 @@ class LangTagsMap():
if lang['tag'] != lang['iso639_3']:
if len(lang['tag']) < 3:
map3To2.append("'%s': '%s'" % (lang['iso639_3'], lang['tag']))
- langTags.append(
- "'%s': {'full': '%s', 'region': '%s', 'script': '%s', 'suppress': %s}" % (lang['tag'], lang['full'], region, script, suppress))
+ langTags.append("'%s': {'full': '%s', 'region': '%s', 'script': '%s', 'suppress': %s}" % (
+ lang['tag'], lang['full'], region, script, suppress))
allTags.append("'%s': '%s'" % (lang['tag'], lang['tag']))
if lang['tag'] != lang['full']:
allTags.append("'%s': '%s'" % (lang['full'], lang['tag']))
@@ -51,9 +54,9 @@ class LangTagsMap():
if tag != lang['full'] and tag != lang['tag']:
allTags.append("'%s': '%s'" % (tag, lang['tag']))
- langTagsString = ',\n '.join(map(str, langTags))
- allTagsString = ',\n '.join(allTags)
- map3To2String = ',\n '.join(map3To2)
- outputFile.write(" __langTags = {\n %s }\n\n" % langTagsString)
- outputFile.write(" __allTags = { %s }\n\n" % allTagsString)
- outputFile.write(" __map3To2 = { %s }\n" % map3To2String)
+ langTagsString = ',\n '.join(map(str, langTags))
+ allTagsString = ',\n '.join(allTags)
+ map3To2String = ',\n '.join(map3To2)
+ outputFile.write(" __langTags = {\n %s}\n\n" % langTagsString)
+ outputFile.write(" __allTags = {\n %s}\n\n" % allTagsString)
+ outputFile.write(" __map3To2 = {\n %s}\n" % map3To2String)
diff --git a/linux/keyman-config/keyman_config/canonical_language_code_utils.py b/linux/keyman-config/keyman_config/canonical_language_code_utils.py
index 016d409742..e2ebb5fd96 100644
--- a/linux/keyman-config/keyman_config/canonical_language_code_utils.py
+++ b/linux/keyman-config/keyman_config/canonical_language_code_utils.py
@@ -13,6 +13,7 @@ except ImportError:
class CanonicalLanguageCodeUtils():
+ @staticmethod
def findBestTag(tag, addRegion, addScriptIfNotSuppressed):
"""
Find a language code with appropriate script and region subtags
diff --git a/linux/keyman-config/keyman_config/downloadkeyboard.py b/linux/keyman-config/keyman_config/downloadkeyboard.py
index 6052b911fe..b219241cbd 100755
--- a/linux/keyman-config/keyman_config/downloadkeyboard.py
+++ b/linux/keyman-config/keyman_config/downloadkeyboard.py
@@ -42,7 +42,7 @@ class DownloadKmpWindow(Gtk.Dialog):
self.resize(800, 450)
self.show_all()
- def _process_kmp(self, url, downloadfile):
+ def _process_kmp(self, url, downloadfile: str):
logging.info("Downloading kmp file to %s", downloadfile)
if download_kmp_file(url, downloadfile):
logging.info("File downloaded")
diff --git a/linux/keyman-config/keyman_config/gnome_keyboards_util.py b/linux/keyman-config/keyman_config/gnome_keyboards_util.py
index ce6fd52db0..4b0d5cfbca 100644
--- a/linux/keyman-config/keyman_config/gnome_keyboards_util.py
+++ b/linux/keyman-config/keyman_config/gnome_keyboards_util.py
@@ -12,6 +12,8 @@ class GnomeKeyboardsUtil():
def read_input_sources(self):
sources = self.input_sources.get('sources')
logging.debug('read sources: %s', sources)
+ if sources is None:
+ return []
return sources
def write_input_sources(self, sources):
diff --git a/linux/keyman-config/keyman_config/gsettings.py b/linux/keyman-config/keyman_config/gsettings.py
index 02afe872a8..02bc2ed920 100644
--- a/linux/keyman-config/keyman_config/gsettings.py
+++ b/linux/keyman-config/keyman_config/gsettings.py
@@ -90,9 +90,9 @@ class GSettings():
if self.is_sudo:
variant = str(value)
subprocess.run(
- ['sudo', '-H', '-u', os.environ.get('SUDO_USER'),
- 'DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%s/bus' % os.environ.get('SUDO_UID'),
- 'gsettings', 'set', self.schema_id, key, variant])
+ ['sudo', '-H', '-u', os.environ.get('SUDO_USER'),
+ 'DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/%s/bus' % os.environ.get('SUDO_UID'),
+ 'gsettings', 'set', self.schema_id, key, variant])
else:
variant = self._convert_array_to_variant(value, type)
self.schema.set_value(key, variant)
diff --git a/linux/keyman-config/keyman_config/install_kmp.py b/linux/keyman-config/keyman_config/install_kmp.py
index e6378abe6a..0fc8f5bf91 100755
--- a/linux/keyman-config/keyman_config/install_kmp.py
+++ b/linux/keyman-config/keyman_config/install_kmp.py
@@ -79,17 +79,17 @@ class InstallKmp():
online (bool, default=False): whether to attempt to get online keyboard data
"""
self._check_keyman_dir(
- '/usr/local/share',
- _("You do not have permissions to install the keyboard files to the shared area "
- "/usr/local/share/keyman"))
+ '/usr/local/share',
+ _("You do not have permissions to install the keyboard files to the shared area "
+ "/usr/local/share/keyman"))
self._check_keyman_dir(
- '/usr/local/share/doc',
- _("You do not have permissions to install the documentation to the shared "
- "documentation area /usr/local/share/doc/keyman"))
+ '/usr/local/share/doc',
+ _("You do not have permissions to install the documentation to the shared "
+ "documentation area /usr/local/share/doc/keyman"))
self._check_keyman_dir(
- '/usr/local/share/fonts',
- _("You do not have permissions to install the font files to the shared font area "
- "/usr/local/share/fonts"))
+ '/usr/local/share/fonts',
+ _("You do not have permissions to install the font files to the shared font area "
+ "/usr/local/share/fonts"))
return self._install_kmp(inputfile, online, language, InstallLocation.Shared)
@@ -128,7 +128,7 @@ class InstallKmp():
inputfile, fileVersion)
rmtree(self.packageDir)
message = _("{packageFile} requires Keyman {keymanVersion} or higher").format(
- packageFile=inputfile, keymanVersion=fileVersion)
+ packageFile=inputfile, keymanVersion=fileVersion)
raise InstallError(InstallStatus.Abort, message)
if keyboards:
logging.info("Installing %s", secure_lookup(info, 'name', 'description'))
@@ -138,6 +138,9 @@ class InstallKmp():
if kb['id'] != self.packageID:
process_keyboard_data(kb['id'], self.packageDir)
+ if files is None:
+ return self.install_keyboards(keyboards, self.packageDir, language)
+
for f in files:
fpath = os.path.join(self.packageDir, f['name'])
ftype = f['type']
@@ -188,7 +191,7 @@ class InstallKmp():
logging.info(o)
rmtree(self.packageDir)
message = _("No kmp.json or kmp.inf found in {packageFile}").format(
- packageFile=inputfile)
+ packageFile=inputfile)
raise InstallError(InstallStatus.Abort, message)
def _safeMakeDirs(self, dir):
@@ -274,7 +277,7 @@ def extract_kmp(kmpfile, directory):
zip_ref.extractall(directory)
-def process_keyboard_data(keyboardID, packageDir):
+def process_keyboard_data(keyboardID, packageDir) -> None:
kbdata = get_keyboard_data(keyboardID)
if kbdata:
if not os.path.isdir(packageDir) and os.access(os.path.join(packageDir, os.pardir), os.X_OK | os.W_OK):
@@ -304,6 +307,8 @@ def install_kmp(inputfile, online=False, sharedarea=False, language=None):
inputfile (str): path to kmp file
online(bool, default=False): whether to attempt to get online keyboard data
sharedarea(bool, default=False): whether install kmp to shared area or user directory
+ language(str, default=None): language to install keyboard for
+ has_ui(bool, default=True): whether we're displaying a window or running UI less from the command line
"""
if sharedarea:
return InstallKmp().install_kmp_shared(inputfile, online, language)
diff --git a/linux/keyman-config/keyman_config/install_window.py b/linux/keyman-config/keyman_config/install_window.py
index 6f71f1b909..052e16067f 100755
--- a/linux/keyman-config/keyman_config/install_window.py
+++ b/linux/keyman-config/keyman_config/install_window.py
@@ -68,8 +68,8 @@ class InstallKmpWindow(Gtk.Dialog):
if not keyboards:
# Likely not a keyboard .kmp file
logging.info("%s is not a Keyman keyboard package" % kmpfile)
- dialog = Gtk.MessageDialog(viewkmp, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK,
- _("The file '{kmpfile}' is not a Keyman keyboard package!").format(kmpfile=kmpfile))
+ dialog = Gtk.MessageDialog(viewkmp, 0, Gtk.MessageType.ERROR, Gtk.ButtonsType.OK, _(
+ "The file '{kmpfile}' is not a Keyman keyboard package!").format(kmpfile=kmpfile))
dialog.run()
dialog.destroy()
self.checkcontinue = False
@@ -83,11 +83,11 @@ class InstallKmpWindow(Gtk.Dialog):
if installed_kmp_ver and secure_lookup(info, 'version', 'description'):
if secure_lookup(info, 'version', 'description') == installed_kmp_ver:
dialog = Gtk.MessageDialog(
- viewkmp, 0, Gtk.MessageType.QUESTION,
- Gtk.ButtonsType.YES_NO, _("Keyboard is installed already"))
+ viewkmp, 0, Gtk.MessageType.QUESTION,
+ Gtk.ButtonsType.YES_NO, _("Keyboard is installed already"))
dialog.format_secondary_text(
- _("The {name} keyboard is already installed at version {version}. "
- "Do you want to uninstall then reinstall it?")
+ _("The {name} keyboard is already installed at version {version}. "
+ "Do you want to uninstall then reinstall it?")
.format(name=self.kbname, version=installed_kmp_ver))
response = dialog.run()
dialog.destroy()
@@ -102,10 +102,11 @@ class InstallKmpWindow(Gtk.Dialog):
try:
logging.info("package version %s", secure_lookup(info, 'version', 'description'))
logging.info("installed kmp version %s", installed_kmp_ver)
- if StrictVersion(secure_lookup(info, 'version', 'description')) <= StrictVersion(installed_kmp_ver):
+ if StrictVersion(secure_lookup(info, 'version',
+ 'description')) <= StrictVersion(installed_kmp_ver):
dialog = Gtk.MessageDialog(
- viewkmp, 0, Gtk.MessageType.QUESTION,
- Gtk.ButtonsType.YES_NO, _("Keyboard is installed already"))
+ viewkmp, 0, Gtk.MessageType.QUESTION,
+ Gtk.ButtonsType.YES_NO, _("Keyboard is installed already"))
dialog.format_secondary_text(
_("The {name} keyboard is already installed with a newer version {installedversion}. "
"Do you want to uninstall it and install the older version {version}?")
@@ -186,14 +187,16 @@ class InstallKmpWindow(Gtk.Dialog):
grid.attach_next_to(label3, prevlabel, Gtk.PositionType.BOTTOM, 1, 1)
prevlabel = label3
label = Gtk.Label()
- if secure_lookup(info, 'version', 'description'):
- label.set_text(secure_lookup(info, 'version', 'description'))
+ description = secure_lookup(info, 'version', 'description')
+ if description:
+ label.set_text(description)
label.set_halign(Gtk.Align.START)
label.set_selectable(True)
grid.attach_next_to(label, label3, Gtk.PositionType.RIGHT, 1, 1)
- if secure_lookup(info, 'author'):
- author = info['author']
+ author = secure_lookup(info, 'author')
+ if author:
+ author = author
label4 = Gtk.Label()
label4.set_text(_("Author: "))
label4.set_halign(Gtk.Align.END)
@@ -202,8 +205,8 @@ class InstallKmpWindow(Gtk.Dialog):
label = Gtk.Label()
if secure_lookup(author, 'url') and secure_lookup(author, 'description'):
label.set_markup(
- "" + author['description'] + "")
+ "" + author['description'] + "")
elif secure_lookup(author, 'description'):
label.set_text(author['description'])
label.set_halign(Gtk.Align.START)
@@ -218,10 +221,10 @@ class InstallKmpWindow(Gtk.Dialog):
grid.attach_next_to(label5, prevlabel, Gtk.PositionType.BOTTOM, 1, 1)
prevlabel = label5
label = Gtk.Label()
- if secure_lookup(info, 'website', 'description'):
+ website_description = secure_lookup(info, 'website', 'description')
+ if website_description:
label.set_markup(
- "" +
- secure_lookup(info, 'website', 'description') + "")
+ "" + website_description + "")
label.set_halign(Gtk.Align.START)
label.set_selectable(True)
grid.attach_next_to(label, label5, Gtk.PositionType.RIGHT, 1, 1)
@@ -232,8 +235,9 @@ class InstallKmpWindow(Gtk.Dialog):
label6.set_halign(Gtk.Align.END)
grid.attach_next_to(label6, prevlabel, Gtk.PositionType.BOTTOM, 1, 1)
label = Gtk.Label()
- if secure_lookup(info, 'copyright', 'description'):
- label.set_text(secure_lookup(info, 'copyright', 'description'))
+ copyright_description = secure_lookup(info, 'copyright', 'description')
+ if copyright_description:
+ label.set_text(copyright_description)
label.set_halign(Gtk.Align.START)
label.set_selectable(True)
grid.attach_next_to(label, label6, Gtk.PositionType.RIGHT, 1, 1)
@@ -242,8 +246,9 @@ class InstallKmpWindow(Gtk.Dialog):
webview = WebKit2.WebView()
webview.connect("decide-policy", self.doc_policy)
- if secure_lookup(options, 'readmeFile'):
- self.readme = options['readmeFile']
+ readmeFile = secure_lookup(options, 'readmeFile')
+ if readmeFile:
+ self.readme = readmeFile
else:
self.readme = "noreadme"
readme_file = os.path.join(tmpdirname, self.readme)
@@ -323,8 +328,8 @@ class InstallKmpWindow(Gtk.Dialog):
# because for fcitx they will need to take extra steps to complete
# installation themselves.
dialog = Gtk.MessageDialog(
- self, 0, Gtk.MessageType.INFO,
- Gtk.ButtonsType.OK, result)
+ self, 0, Gtk.MessageType.INFO,
+ Gtk.ButtonsType.OK, result)
dialog.run()
dialog.destroy()
if is_fcitx_running():
@@ -350,12 +355,12 @@ class InstallKmpWindow(Gtk.Dialog):
except InstallError as e:
if e.status == InstallStatus.Abort:
message = _("Keyboard {name} could not be installed.").format(name=self.kbname) \
- + "\n\n" + _("Error Message:") + "\n %s" % (e.message)
+ + "\n\n" + _("Error Message:") + "\n %s" % (e.message)
logging.error(message)
message_type = Gtk.MessageType.ERROR
else:
message = _("Keyboard {name} could not be installed.").format(name=self.kbname) \
- + "\n\n" + _("Warning Message:") + "\n %s" % (e.message)
+ + "\n\n" + _("Warning Message:") + "\n %s" % (e.message)
logging.warning(message)
message_type = Gtk.MessageType.WARNING
dialog = Gtk.MessageDialog(
diff --git a/linux/keyman-config/keyman_config/uninstall_kmp.py b/linux/keyman-config/keyman_config/uninstall_kmp.py
index 1c96689213..4a96b9040b 100755
--- a/linux/keyman-config/keyman_config/uninstall_kmp.py
+++ b/linux/keyman-config/keyman_config/uninstall_kmp.py
@@ -11,7 +11,7 @@ from keyman_config.ibus_util import uninstall_from_ibus, get_ibus_bus, restart_i
from keyman_config.gnome_keyboards_util import GnomeKeyboardsUtil, get_ibus_keyboard_id, is_gnome_shell
-def delete_dir(dir):
+def delete_dir(dir: str) -> bool:
if not os.path.isdir(dir):
logging.error("%s is not a directory", dir)
return False
@@ -40,12 +40,12 @@ def uninstall_kmp_shared(packageID):
logging.info("Uninstalling shared keyboard: %s", packageID)
if not os.access(kbdir, os.X_OK | os.W_OK): # Check for write access of keyman dir
logging.error(
- "You do not have permissions to uninstall the keyboard files. You need to run this with `sudo`")
+ "You do not have permissions to uninstall the keyboard files. You need to run this with `sudo`")
exit(3)
if os.path.isdir(kbdocdir):
if not os.access(kbdocdir, os.X_OK | os.W_OK): # Check for write access of keyman doc dir
logging.error(
- "You do not have permissions to uninstall the documentation. You need to run this with `sudo`")
+ "You do not have permissions to uninstall the documentation. You need to run this with `sudo`")
exit(3)
delete_dir(kbdocdir)
logging.info("Removed documentation directory: %s", kbdocdir)
@@ -54,7 +54,7 @@ def uninstall_kmp_shared(packageID):
if os.path.isdir(kbfontdir):
if not os.access(kbfontdir, os.X_OK | os.W_OK): # Check for write access of keyman fonts
logging.error(
- "You do not have permissions to uninstall the font files. You need to run this with `sudo`")
+ "You do not have permissions to uninstall the font files. You need to run this with `sudo`")
exit(3)
delete_dir(kbfontdir)
logging.info("Removed font directory: %s", kbfontdir)
diff --git a/linux/keyman-config/keyman_config/view_installed.py b/linux/keyman-config/keyman_config/view_installed.py
index c873d71582..23f04e8091 100755
--- a/linux/keyman-config/keyman_config/view_installed.py
+++ b/linux/keyman-config/keyman_config/view_installed.py
@@ -59,8 +59,8 @@ class ViewInstalledWindowBase(Gtk.Window):
def on_installfile_clicked(self, button):
logging.debug("Install from file clicked")
dlg = Gtk.FileChooserDialog(
- _("Choose a kmp file..."), self, Gtk.FileChooserAction.OPEN,
- (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
+ _("Choose a kmp file..."), self, Gtk.FileChooserAction.OPEN,
+ (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL, Gtk.STOCK_OPEN, Gtk.ResponseType.OK))
dlg.resize(640, 480)
filter_text = Gtk.FileFilter()
# i18n: file type in file selection dialog
diff --git a/linux/keyman-config/km-package-install b/linux/keyman-config/km-package-install
index 0d4c458cad..b1fbb36c80 100755
--- a/linux/keyman-config/km-package-install
+++ b/linux/keyman-config/km-package-install
@@ -1,21 +1,22 @@
#!/usr/bin/python3
import argparse
-from distutils.version import StrictVersion
-import logging
-import sys
-import os
-from keyman_config import __version__, KeymanApiUrl, secure_lookup
-from keyman_config.uninstall_kmp import uninstall_kmp
-
import datetime
+import logging
+import os
+import sys
import time
+from distutils.version import StrictVersion
from zipfile import is_zipfile
+from keyman_config import KeymanApiUrl, __version__, secure_lookup
+from keyman_config.uninstall_kmp import uninstall_kmp
+
def get_languages():
import requests
import requests_cache
+
from keyman_config.get_kmp import keyman_cache_dir
logging.info("Getting language list from search")
@@ -45,6 +46,9 @@ def get_languages():
def get_keyboard_list():
languages = get_languages()
keyboards = []
+ if not languages:
+ return []
+
if "languages" in languages:
for lang in languages["languages"]:
if "keyboards" in lang:
@@ -82,8 +86,8 @@ def list_keyboards():
def main():
parser = argparse.ArgumentParser(
- description='Install a Keyman keyboard package, either a local .kmp file or specify a ' +
- 'keyboard id to download and install')
+ description='Install a Keyman keyboard package, either a local .kmp file or specify a ' +
+ 'keyboard id to download and install')
parser.add_argument('-s', '--shared', action='store_true', help='Install to shared area /usr/local')
parser.add_argument('-f', '--file', metavar='KMPFILE', help='Keyman kmp file')
parser.add_argument('-p', '--package', metavar='PACKAGE', help='Keyman package id')
@@ -102,13 +106,15 @@ def main():
if args.package and args.file:
parser.print_usage()
logging.error(
- "km-package-install: error: too many arguments: either install a local kmp file or " +
- "specify a keyboard id to download and install.")
+ "km-package-install: error: too many arguments: either install a local kmp file or " +
+ "specify a keyboard id to download and install.")
sys.exit(2)
- from keyman_config.install_kmp import install_kmp, InstallError, InstallStatus
+ from keyman_config.get_kmp import (get_keyboard_data, get_kmp,
+ keyman_cache_dir)
+ from keyman_config.install_kmp import (InstallError, InstallStatus,
+ install_kmp)
from keyman_config.list_installed_kmp import get_kmp_version
- from keyman_config.get_kmp import get_keyboard_data, get_kmp, keyman_cache_dir
if os.path.exists(os.path.join(keyman_cache_dir(), 'kmpdirlist')):
os.remove(os.path.join(keyman_cache_dir(), 'kmpdirlist'))
@@ -165,8 +171,8 @@ def main():
else:
parser.print_usage()
logging.error(
- "km-package-install: error: no arguments: either install a local kmp file " +
- "or specify a keyboard package id to download and install.")
+ "km-package-install: error: no arguments: either install a local kmp file " +
+ "or specify a keyboard package id to download and install.")
sys.exit(2)