diff --git a/linux/keyman-config/.editorconfig b/linux/keyman-config/.editorconfig index 020438e0c6..6707d70e59 100644 --- a/linux/keyman-config/.editorconfig +++ b/linux/keyman-config/.editorconfig @@ -2,3 +2,6 @@ [*] indent_style = space indent_size = 4 + +[*.sharedmimeinfo] +indent_style = tab \ No newline at end of file diff --git a/linux/keyman-config/debian/keyman.sharedmimeinfo b/linux/keyman-config/debian/keyman.sharedmimeinfo index 273dcf9d8d..569866b403 100644 --- a/linux/keyman-config/debian/keyman.sharedmimeinfo +++ b/linux/keyman-config/debian/keyman.sharedmimeinfo @@ -6,4 +6,7 @@ + + Keyman keyboard installation link + diff --git a/linux/keyman-config/debian/km-config.desktop b/linux/keyman-config/debian/km-config.desktop index e37c297054..83bf1a8b99 100644 --- a/linux/keyman-config/debian/km-config.desktop +++ b/linux/keyman-config/debian/km-config.desktop @@ -3,7 +3,7 @@ Name=Keyman Keyboards Name[en_GB]=Keyman Keyboards Comment=Configure Keyman keyboards Comment[en_GB]=Configure Keyman keyboards -Exec=km-config -i %f +Exec=km-config -i %u Icon=km-config Terminal=false Type=Application @@ -11,4 +11,4 @@ StartupNotify=true Categories=Settings; Keywords=keyman;keyboard;input; X-Desktop-File-Install-Version=0.21 -MimeType=application/x-kmp;x-scheme-handler/x-kmp +MimeType=application/x-kmp;x-scheme-handler/x-kmp;application/keyman;x-scheme-handler/keyman diff --git a/linux/keyman-config/keyman_config/handle_install.py b/linux/keyman-config/keyman_config/handle_install.py new file mode 100644 index 0000000000..af341fda33 --- /dev/null +++ b/linux/keyman-config/keyman_config/handle_install.py @@ -0,0 +1,63 @@ +import logging +import os + +from urllib.parse import parse_qs, urlparse +from keyman_config import KeymanComUrl, __tier__ +from keyman_config.install_window import InstallKmpWindow +from keyman_config.get_kmp import get_download_folder, download_kmp_file + + +def download_and_install_package(url): + """ + Handle the download and installation of the given package. This can either be a .kmp + file that got downloaded previously, or a keyman:// URL which will be downloaded and + installed. + + Args: + url: a .kmp file, a keyman:// URL, or a file:// URL pointing to a .kmp file, + possibly with a bcp47= specified + """ + parsedUrl = urlparse(url) + bcp47 = _extract_bcp47(parsedUrl.query) + + if parsedUrl.scheme == 'keyman': + logging.info("downloading " + url) + if not url.startswith('keyman://download/keyboard/'): + logging.error("Don't know what to do with URL " + url) + return + + packageId = parsedUrl.path[len('/keyboard/'):] + if not packageId: + logging.error("Missing package id") + return + + downloadFile = os.path.join(get_download_folder(), packageId) + downloadUrl = KeymanComUrl + '/go/package/download/' + packageId + '?platform=linux&tier=' + __tier__ + packageFile = download_kmp_file(downloadUrl, downloadFile) + elif parsedUrl.scheme == '' or parsedUrl.scheme == 'file': + packageFile = parsedUrl.path + else: + logging.error("Invalid URL: " + url) + return + + if not _install_package(packageFile, bcp47): + logging.error("Can't find file " + url) + + +def _extract_bcp47(query): + if query: + queryStrings = parse_qs(query) + values = queryStrings['bcp47'] + if len(values) > 0: + return values[0] + return '' + + +def _install_package(packageFile, bcp47): + if not os.path.isfile(packageFile): + return False + + w = InstallKmpWindow(packageFile, language=bcp47) + w.run() + w.destroy() + return True diff --git a/linux/keyman-config/km-config b/linux/keyman-config/km-config index d362340732..a8cd4c2b6f 100755 --- a/linux/keyman-config/km-config +++ b/linux/keyman-config/km-config @@ -2,9 +2,9 @@ import argparse import logging -import os from keyman_config import __version__ +from keyman_config.handle_install import download_and_install_package if __name__ == '__main__': @@ -23,13 +23,7 @@ if __name__ == '__main__': logging.basicConfig(format='%(levelname)s:%(message)s') if args.install: - if os.path.isfile(args.install): - from keyman_config.install_window import InstallKmpWindow - w = InstallKmpWindow(args.install) - w.run() - w.destroy() - else: - logging.error("Can't find file " + args.install) + download_and_install_package(args.install) else: from keyman_config.view_installed import ViewInstalledWindow w = ViewInstalledWindow() diff --git a/linux/keyman-config/tests/test_handle_install.py b/linux/keyman-config/tests/test_handle_install.py new file mode 100644 index 0000000000..a2745e5623 --- /dev/null +++ b/linux/keyman-config/tests/test_handle_install.py @@ -0,0 +1,106 @@ +#!/usr/bin/python3 +import unittest +from unittest.mock import patch + +from keyman_config import KeymanComUrl +from keyman_config.handle_install import download_and_install_package + + +class HandleInstallTests(unittest.TestCase): + + @patch('keyman_config.handle_install._install_package') + def test_downloadAndInstallPackage_file(self, installPackageMethod): + # Execute + download_and_install_package('/tmp/keyboard/sil_euro_latin.kmp') + + # Verify + installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', '') + + @patch('keyman_config.handle_install._install_package') + def test_downloadAndInstallPackage_fileUrl(self, installPackageMethod): + # Execute + download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp') + + # Verify + installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', '') + + @patch('keyman_config.handle_install._install_package') + def test_downloadAndInstallPackage_fileUrlWithBcp47(self, installPackageMethod): + # Execute + download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp?bcp47=dyo') + + # Verify + installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', 'dyo') + + @patch('keyman_config.handle_install._install_package') + def test_downloadAndInstallPackage_fileUrlWithBcp47AndVersion(self, installPackageMethod): + # Execute + download_and_install_package('file:///tmp/keyboard/sil_euro_latin.kmp?bcp47=dyo&version=1') + + # Verify + installPackageMethod.assert_called_with('/tmp/keyboard/sil_euro_latin.kmp', 'dyo') + + @patch('keyman_config.handle_install._install_package') + def test_downloadAndInstallPackage_InvalidUrl(self, installPackageMethod): + # Execute + download_and_install_package('http://localhost/keyboard/sil_euro_latin.kmp') + + # Verify + installPackageMethod.assert_not_called() + + @patch('keyman_config.handle_install._install_package') + @patch('keyman_config.get_kmp.download_kmp_file') + def test_downloadAndInstallPackage_invalidUrl(self, downloadKmpFileMethod, + installPackageMethod): + for url in ['foo://download/keyboard/sil_euro_latin', 'keyman://keyboard/sil_euro_latin', + 'keyman://download/sil_euro_latin', 'keyman://download/keyboard/']: + with self.subTest(url=url): + # Execute + download_and_install_package(url) + + # Verify + downloadKmpFileMethod.assert_not_called() + installPackageMethod.assert_not_called() + + @patch('keyman_config.handle_install._install_package') + @patch('keyman_config.get_kmp.keyman_cache_dir') + @patch('keyman_config.handle_install.download_kmp_file') + def test_downloadAndInstallPackage_keymanUrl(self, downloadKmpFileMethod, + keymanCacheDirMethod, installPackageMethod): + # Setup + mockPackagePath = '/tmp/sil_euro_latin' + keymanCacheDirMethod.return_value = '/tmp' + downloadKmpFileMethod.return_value = mockPackagePath + + # Execute + download_and_install_package('keyman://download/keyboard/sil_euro_latin') + + # Verify + downloadKmpFileMethod.assert_called_with( + KeymanComUrl + '/go/package/download/sil_euro_latin?platform=linux&tier=alpha', + mockPackagePath) + installPackageMethod.assert_called_with(mockPackagePath, '') + + @patch('keyman_config.handle_install._install_package') + @patch('keyman_config.get_kmp.keyman_cache_dir') + @patch('keyman_config.handle_install.download_kmp_file') + def test_downloadAndInstallPackage_keymanUrlWithBcp47(self, downloadKmpFileMethod, + keymanCacheDirMethod, + installPackageMethod): + # Setup + mockPackagePath = '/tmp/sil_euro_latin' + keymanCacheDirMethod.return_value = '/tmp' + downloadKmpFileMethod.return_value = mockPackagePath + + # Execute + download_and_install_package('keyman://download/keyboard/sil_euro_latin?bcp47=de') + + # Verify + downloadKmpFileMethod.assert_called_with( + KeymanComUrl + '/go/package/download/sil_euro_latin?platform=linux&tier=alpha', + mockPackagePath) + installPackageMethod.assert_called_with(mockPackagePath, 'de') + + +if __name__ == '__main__': + unittest.main()