From 3a82abe8f200222b2864c1ee986dcdbd081d2863 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 12 Jan 2023 17:54:32 +0100 Subject: [PATCH 1/4] feat(linux): Improve uninstallation Even if the directory doesn't exist, we can still remove the keyboard from the keyboard list. --- .../keyman_config/uninstall_kmp.py | 44 ++++++++++--------- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/linux/keyman-config/keyman_config/uninstall_kmp.py b/linux/keyman-config/keyman_config/uninstall_kmp.py index 84c083694d..972c417b63 100755 --- a/linux/keyman-config/keyman_config/uninstall_kmp.py +++ b/linux/keyman-config/keyman_config/uninstall_kmp.py @@ -36,15 +36,26 @@ def uninstall_kmp_shared(packageID): packageID (str): Keyboard package ID """ kbdir = get_keyboard_dir(InstallLocation.Shared, packageID) + kbdocdir = get_keyman_doc_dir(InstallLocation.Shared, packageID) + kbfontdir = get_keyman_font_dir(InstallLocation.Shared, packageID) + + logging.info("Uninstalling shared keyboard: %s", packageID) + + # need to uninstall from ibus for all lang and all kmx in kmp + info, system, options, keyboards, files = get_metadata(kbdir) + if keyboards: + if is_gnome_shell(): + uninstall_keyboards_from_gnome(keyboards, kbdir) + else: + uninstall_keyboards_from_ibus(keyboards, kbdir) + else: + logging.warning("could not uninstall keyboards") + if not os.path.isdir(kbdir): msg = _("Keyboard directory for %s does not exist." % packageID) logging.error(msg) return msg - kbdocdir = get_keyman_doc_dir(InstallLocation.Shared, packageID) - kbfontdir = get_keyman_font_dir(InstallLocation.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 msg = _("You do not have permissions to uninstall the keyboard files. You need to run this with `sudo`") logging.error(msg) @@ -68,16 +79,6 @@ def uninstall_kmp_shared(packageID): else: logging.info("No font directory") - # need to uninstall from ibus for all lang and all kmx in kmp - info, system, options, keyboards, files = get_metadata(kbdir) - if keyboards: - if is_gnome_shell(): - uninstall_keyboards_from_gnome(keyboards, kbdir) - else: - uninstall_keyboards_from_ibus(keyboards, kbdir) - else: - logging.warning("could not uninstall keyboards") - delete_dir(kbdir) logging.info("Removed keyman directory: %s", kbdir) logging.info("Finished uninstalling shared keyboard: %s", packageID) @@ -130,11 +131,8 @@ def uninstall_kmp_user(packageID): Args: packageID (str): Keyboard package ID """ + msg = '' kbdir = get_keyboard_dir(InstallLocation.User, packageID) - if not os.path.isdir(kbdir): - msg = _("Keyboard directory for %s does not exist." % packageID) - logging.error(msg) - return msg logging.info("Uninstalling local keyboard: %s", packageID) info, system, options, keyboards, files = get_metadata(kbdir) if keyboards: @@ -146,14 +144,18 @@ def uninstall_kmp_user(packageID): uninstall_keyboards_from_ibus(keyboards, kbdir) else: logging.warning("could not uninstall keyboards") - delete_dir(kbdir) - logging.info("Removed user keyman directory: %s", kbdir) + if not os.path.isdir(kbdir): + msg = _("Keyboard directory for %s does not exist." % packageID) + logging.error(msg) + else: + delete_dir(kbdir) + logging.info("Removed user keyman directory: %s", kbdir) fontdir = get_keyman_font_dir(InstallLocation.User, packageID) if os.path.isdir(fontdir): delete_dir(fontdir) logging.info("Removed user keyman font directory: %s", fontdir) logging.info("Finished uninstalling local keyboard: %s", packageID) - return '' + return msg def uninstall_kmp(packageID, sharedarea=False): From 167f42aad8f6941cb70fda82c618ba33bc1800ef Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Mon, 16 Jan 2023 10:50:47 +0100 Subject: [PATCH 2/4] feat(linux): Don't show error if dir doesn't exist during uninstall Don't show an error to the user if the keyboard directory doesn't exist during uninstall. Only log the error. See https://github.com/keymanapp/keyman/pull/8011#discussion_r1070197093. --- linux/keyman-config/keyman_config/uninstall_kmp.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/linux/keyman-config/keyman_config/uninstall_kmp.py b/linux/keyman-config/keyman_config/uninstall_kmp.py index 972c417b63..40265a51f5 100755 --- a/linux/keyman-config/keyman_config/uninstall_kmp.py +++ b/linux/keyman-config/keyman_config/uninstall_kmp.py @@ -131,7 +131,6 @@ def uninstall_kmp_user(packageID): Args: packageID (str): Keyboard package ID """ - msg = '' kbdir = get_keyboard_dir(InstallLocation.User, packageID) logging.info("Uninstalling local keyboard: %s", packageID) info, system, options, keyboards, files = get_metadata(kbdir) @@ -145,8 +144,7 @@ def uninstall_kmp_user(packageID): else: logging.warning("could not uninstall keyboards") if not os.path.isdir(kbdir): - msg = _("Keyboard directory for %s does not exist." % packageID) - logging.error(msg) + logging.error("Keyboard directory for %s does not exist." % packageID) else: delete_dir(kbdir) logging.info("Removed user keyman directory: %s", kbdir) @@ -155,7 +153,7 @@ def uninstall_kmp_user(packageID): delete_dir(fontdir) logging.info("Removed user keyman font directory: %s", fontdir) logging.info("Finished uninstalling local keyboard: %s", packageID) - return msg + return '' def uninstall_kmp(packageID, sharedarea=False): From 93841aad22c8288a1f8e875502bf151c3383fc76 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 19 Jan 2023 12:45:14 +0100 Subject: [PATCH 3/4] feat(linux): Improve uninstall errors for userdata This change addresses the code review comments, so that the uninstallation tries to delete all three directories (keyboard, documentation, font). It also adds the same logic to keyboards installed in the User area. --- .../keyman_config/uninstall_kmp.py | 113 ++++++++++++------ 1 file changed, 77 insertions(+), 36 deletions(-) diff --git a/linux/keyman-config/keyman_config/uninstall_kmp.py b/linux/keyman-config/keyman_config/uninstall_kmp.py index 40265a51f5..617ee3da67 100755 --- a/linux/keyman-config/keyman_config/uninstall_kmp.py +++ b/linux/keyman-config/keyman_config/uninstall_kmp.py @@ -28,6 +28,45 @@ def delete_dir(dir: str) -> bool: return True +def _uninstall_kbdir(packageID, kbdir): + if not os.path.isdir(kbdir): + msg = _('Keyboard directory for %s does not exist.') % packageID + logging.error(msg) + return msg + + if not os.access(kbdir, os.X_OK | os.W_OK): # Check for write access of keyman dir + msg = _('You do not have permissions to uninstall the keyboard files in %s. You need to run this with `sudo`') % kbdir + logging.error(msg) + return (True, msg) + + delete_dir(kbdir) + return (False, 'Removed keyman directory: %s' % kbdir) + + +def _uninstall_docdir(kbdocdir): + if os.path.isdir(kbdocdir): + if not os.access(kbdocdir, os.X_OK | os.W_OK): # Check for write access of keyman doc dir + msg = _('You do not have permissions to uninstall the documentation in %s. You need to run this with `sudo`') % kbdocdir + logging.error(msg) + return (True, msg) + delete_dir(kbdocdir) + return (False, 'Removed documentation directory: %s' % kbdocdir) + else: + return (False, 'No documentation directory') + + +def _uninstall_fontdir(kbfontdir): + if os.path.isdir(kbfontdir): + if not os.access(kbfontdir, os.X_OK | os.W_OK): # Check for write access of keyman fonts + msg = _('You do not have permissions to uninstall the font files in %s. You need to run this with `sudo`') % kbfontdir + logging.error(msg) + return (True, msg) + delete_dir(kbfontdir) + return (False, 'Removed font directory: %s' % kbfontdir) + else: + return (False, 'No font directory') + + def uninstall_kmp_shared(packageID): """ Uninstall a kmp from /usr/local/share/keyman @@ -51,36 +90,28 @@ def uninstall_kmp_shared(packageID): else: logging.warning("could not uninstall keyboards") - if not os.path.isdir(kbdir): - msg = _("Keyboard directory for %s does not exist." % packageID) - logging.error(msg) - return msg - - if not os.access(kbdir, os.X_OK | os.W_OK): # Check for write access of keyman dir - msg = _("You do not have permissions to uninstall the keyboard files. You need to run this with `sudo`") - logging.error(msg) - return msg - if os.path.isdir(kbdocdir): - if not os.access(kbdocdir, os.X_OK | os.W_OK): # Check for write access of keyman doc dir - msg = _("You do not have permissions to uninstall the documentation. You need to run this with `sudo`") - logging.error(msg) - return msg - delete_dir(kbdocdir) - logging.info("Removed documentation directory: %s", kbdocdir) + errormsg = '' + (error, msg) = _uninstall_docdir(kbdocdir) + if error: + errormsg += '\n' + msg else: - logging.info("No documentation directory") - if os.path.isdir(kbfontdir): - if not os.access(kbfontdir, os.X_OK | os.W_OK): # Check for write access of keyman fonts - msg = _("You do not have permissions to uninstall the font files. You need to run this with `sudo`") - logging.error(msg) - return msg - delete_dir(kbfontdir) - logging.info("Removed font directory: %s", kbfontdir) - else: - logging.info("No font directory") + logging.info(msg) + + (error, msg) = _uninstall_fontdir(kbfontdir) + if error: + errormsg += '\n' + msg + else: + logging.info(msg) + + (error, msg) = _uninstall_kbdir(packageID, kbdir) + if error: + errormsg += '\n' + msg + else: + logging.info(msg) + + if errormsg: + return errormsg - delete_dir(kbdir) - logging.info("Removed keyman directory: %s", kbdir) logging.info("Finished uninstalling shared keyboard: %s", packageID) return '' @@ -143,15 +174,25 @@ def uninstall_kmp_user(packageID): uninstall_keyboards_from_ibus(keyboards, kbdir) else: logging.warning("could not uninstall keyboards") - if not os.path.isdir(kbdir): - logging.error("Keyboard directory for %s does not exist." % packageID) + + errormsg = '' + (error, msg) = _uninstall_fontdir(get_keyman_font_dir(InstallLocation.User, packageID)) + if error: + errormsg += '\n' + msg else: - delete_dir(kbdir) - logging.info("Removed user keyman directory: %s", kbdir) - fontdir = get_keyman_font_dir(InstallLocation.User, packageID) - if os.path.isdir(fontdir): - delete_dir(fontdir) - logging.info("Removed user keyman font directory: %s", fontdir) + logging.info(msg) + + # in the User area, docdir is the same as kbdir, so we skip that here + + (error, msg) = _uninstall_kbdir(packageID, kbdir) + if error: + errormsg += '\n' + msg + else: + logging.info(msg) + + if errormsg: + return errormsg + logging.info("Finished uninstalling local keyboard: %s", packageID) return '' From efd52000503a217e68c6784556c10794c5a2cb34 Mon Sep 17 00:00:00 2001 From: Eberhard Beilharz Date: Thu, 19 Jan 2023 18:01:30 +0100 Subject: [PATCH 4/4] chore(linux): More refactoring of uninstall This change refactors and cleans uninstall: - rename methods to make it clear which ones are private/protected - extract common code - improve error reporting --- .../keyman_config/uninstall_kmp.py | 157 +++++------------- .../keyman-config/tests/test_uninstall_kmp.py | 20 +-- 2 files changed, 49 insertions(+), 128 deletions(-) diff --git a/linux/keyman-config/keyman_config/uninstall_kmp.py b/linux/keyman-config/keyman_config/uninstall_kmp.py index 617ee3da67..8eaac8f578 100755 --- a/linux/keyman-config/keyman_config/uninstall_kmp.py +++ b/linux/keyman-config/keyman_config/uninstall_kmp.py @@ -17,7 +17,10 @@ from keyman_config.ibus_util import (get_ibus_bus, restart_ibus, from keyman_config.kmpmetadata import get_metadata -def delete_dir(dir: str) -> bool: +error_dirs = set() + + +def _delete_dir(dir: str) -> bool: if not os.path.isdir(dir): logging.error("%s is not a directory", dir) return False @@ -28,95 +31,55 @@ def delete_dir(dir: str) -> bool: return True -def _uninstall_kbdir(packageID, kbdir): - if not os.path.isdir(kbdir): - msg = _('Keyboard directory for %s does not exist.') % packageID - logging.error(msg) - return msg +def _uninstall_dir(what, dir): + if os.path.isdir(dir): + if not os.access(dir, os.X_OK | os.W_OK): + error_dirs.add(dir) + return - if not os.access(kbdir, os.X_OK | os.W_OK): # Check for write access of keyman dir - msg = _('You do not have permissions to uninstall the keyboard files in %s. You need to run this with `sudo`') % kbdir - logging.error(msg) - return (True, msg) - - delete_dir(kbdir) - return (False, 'Removed keyman directory: %s' % kbdir) - - -def _uninstall_docdir(kbdocdir): - if os.path.isdir(kbdocdir): - if not os.access(kbdocdir, os.X_OK | os.W_OK): # Check for write access of keyman doc dir - msg = _('You do not have permissions to uninstall the documentation in %s. You need to run this with `sudo`') % kbdocdir - logging.error(msg) - return (True, msg) - delete_dir(kbdocdir) - return (False, 'Removed documentation directory: %s' % kbdocdir) + _delete_dir(dir) + logging.info('Removed %s directory %s', what, dir) else: - return (False, 'No documentation directory') + logging.info('No %s directory %s', what, dir) -def _uninstall_fontdir(kbfontdir): - if os.path.isdir(kbfontdir): - if not os.access(kbfontdir, os.X_OK | os.W_OK): # Check for write access of keyman fonts - msg = _('You do not have permissions to uninstall the font files in %s. You need to run this with `sudo`') % kbfontdir - logging.error(msg) - return (True, msg) - delete_dir(kbfontdir) - return (False, 'Removed font directory: %s' % kbfontdir) - else: - return (False, 'No font directory') +def _uninstall_kmp_common(location, packageID): + kbdir = get_keyboard_dir(location, packageID) + kbdocdir = get_keyman_doc_dir(location, packageID) + kbfontdir = get_keyman_font_dir(location, packageID) + where = 'local' + if location == InstallLocation.Shared: + where = 'shared' -def uninstall_kmp_shared(packageID): - """ - Uninstall a kmp from /usr/local/share/keyman - - Args: - packageID (str): Keyboard package ID - """ - kbdir = get_keyboard_dir(InstallLocation.Shared, packageID) - kbdocdir = get_keyman_doc_dir(InstallLocation.Shared, packageID) - kbfontdir = get_keyman_font_dir(InstallLocation.Shared, packageID) - - logging.info("Uninstalling shared keyboard: %s", packageID) - - # need to uninstall from ibus for all lang and all kmx in kmp + logging.info("Uninstalling %s keyboard: %s", where, packageID) info, system, options, keyboards, files = get_metadata(kbdir) if keyboards: - if is_gnome_shell(): - uninstall_keyboards_from_gnome(keyboards, kbdir) + if is_fcitx_running(): + _uninstall_keyboards_from_fcitx5() + elif is_gnome_shell(): + _uninstall_keyboards_from_gnome(keyboards, kbdir) else: - uninstall_keyboards_from_ibus(keyboards, kbdir) + _uninstall_keyboards_from_ibus(keyboards, kbdir) else: logging.warning("could not uninstall keyboards") - errormsg = '' - (error, msg) = _uninstall_docdir(kbdocdir) - if error: - errormsg += '\n' + msg - else: - logging.info(msg) + if not os.path.isdir(kbdir): + logging.error('Keyboard directory %s for %s does not exist.', kbdir, packageID) - (error, msg) = _uninstall_fontdir(kbfontdir) - if error: - errormsg += '\n' + msg - else: - logging.info(msg) + _uninstall_dir('Keyman keyboards', kbdir) + _uninstall_dir('documentation', kbdocdir) + _uninstall_dir('font', kbfontdir) - (error, msg) = _uninstall_kbdir(packageID, kbdir) - if error: - errormsg += '\n' + msg - else: - logging.info(msg) + if error_dirs: + msg = _('You do not have permission to uninstall the files in %s. You need to run this with `sudo`.') % ', '.join(error_dirs) + logging.error(msg) + return msg - if errormsg: - return errormsg - - logging.info("Finished uninstalling shared keyboard: %s", packageID) + logging.info("Finished uninstalling %s keyboard: %s", where, packageID) return '' - -def uninstall_keyboards_from_ibus(keyboards, packageDir): +def _uninstall_keyboards_from_ibus(keyboards, packageDir): bus = get_ibus_bus() if bus or os.environ.get('SUDO_USER'): # install all kmx for first lang not just packageID @@ -128,7 +91,7 @@ def uninstall_keyboards_from_ibus(keyboards, packageDir): logging.warning("could not uninstall keyboards from IBus") -def uninstall_keyboards_from_gnome(keyboards, packageDir): +def _uninstall_keyboards_from_gnome(keyboards, packageDir): gnomeKeyboardsUtil = GnomeKeyboardsUtil() sources = gnomeKeyboardsUtil.read_input_sources() @@ -155,48 +118,6 @@ def _uninstall_keyboards_from_fcitx5(): return _('Please use fcitx5-configtool to remove the keyboard from the group') -def uninstall_kmp_user(packageID): - """ - Uninstall a kmp from ~/.local/share/keyman - - Args: - packageID (str): Keyboard package ID - """ - kbdir = get_keyboard_dir(InstallLocation.User, packageID) - logging.info("Uninstalling local keyboard: %s", packageID) - info, system, options, keyboards, files = get_metadata(kbdir) - if keyboards: - if is_fcitx_running(): - _uninstall_keyboards_from_fcitx5() - elif is_gnome_shell(): - uninstall_keyboards_from_gnome(keyboards, kbdir) - else: - uninstall_keyboards_from_ibus(keyboards, kbdir) - else: - logging.warning("could not uninstall keyboards") - - errormsg = '' - (error, msg) = _uninstall_fontdir(get_keyman_font_dir(InstallLocation.User, packageID)) - if error: - errormsg += '\n' + msg - else: - logging.info(msg) - - # in the User area, docdir is the same as kbdir, so we skip that here - - (error, msg) = _uninstall_kbdir(packageID, kbdir) - if error: - errormsg += '\n' + msg - else: - logging.info(msg) - - if errormsg: - return errormsg - - logging.info("Finished uninstalling local keyboard: %s", packageID) - return '' - - def uninstall_kmp(packageID, sharedarea=False): """ Uninstall a kmp @@ -206,9 +127,9 @@ def uninstall_kmp(packageID, sharedarea=False): sharedarea (str): whether to uninstall from shared /usr/local or ~/.local """ if sharedarea: - msg = uninstall_kmp_shared(packageID) + msg = _uninstall_kmp_common(InstallLocation.Shared, packageID) else: - msg = uninstall_kmp_user(packageID) + msg = _uninstall_kmp_common(InstallLocation.User, packageID) get_keyman_config_service().keyboard_list_changed() return msg diff --git a/linux/keyman-config/tests/test_uninstall_kmp.py b/linux/keyman-config/tests/test_uninstall_kmp.py index a6e2aa301b..4c48200f4c 100644 --- a/linux/keyman-config/tests/test_uninstall_kmp.py +++ b/linux/keyman-config/tests/test_uninstall_kmp.py @@ -2,7 +2,7 @@ import unittest from unittest.mock import patch -from keyman_config.uninstall_kmp import uninstall_keyboards_from_gnome +from keyman_config.uninstall_kmp import _uninstall_keyboards_from_gnome class UninstallKmpTests(unittest.TestCase): @@ -17,7 +17,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance = self.mockGnomeKeyboardsUtilClass.return_value mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [] # Execute - uninstall_keyboards_from_gnome([{'id': 'foo1'}], 'fooDir') + _uninstall_keyboards_from_gnome([{'id': 'foo1'}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with([]) @@ -27,7 +27,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [ ('ibus', 'fooDir/foo2.kmx')] # Execute - uninstall_keyboards_from_gnome([{'id': 'foo1'}], 'fooDir') + _uninstall_keyboards_from_gnome([{'id': 'foo1'}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with([ ('ibus', 'fooDir/foo2.kmx')]) @@ -38,7 +38,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [ ('xkb', 'en'), ('ibus', 'fooDir/foo1.kmx')] # Execute - uninstall_keyboards_from_gnome([{'id': 'foo1'}], 'fooDir') + _uninstall_keyboards_from_gnome([{'id': 'foo1'}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with( [('xkb', 'en')]) @@ -49,7 +49,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [ ('xkb', 'en'), ('ibus', 'fooDir/foo1.kmx'), ('ibus', 'fooDir/foo2.kmx')] # Execute - uninstall_keyboards_from_gnome([{'id': 'foo1'}, {'id': 'foo2'}], 'fooDir') + _uninstall_keyboards_from_gnome([{'id': 'foo1'}, {'id': 'foo2'}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with( [('xkb', 'en')]) @@ -60,7 +60,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [ ('ibus', 'fooDir/foo1.kmx'), ('ibus', 'fooDir/foo2.kmx')] # Execute - uninstall_keyboards_from_gnome([{'id': 'foo1'}, {'id': 'foo2'}], 'fooDir') + _uninstall_keyboards_from_gnome([{'id': 'foo1'}, {'id': 'foo2'}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with([]) @@ -70,7 +70,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [ ('xkb', 'en'), ('ibus', 'en:fooDir/foo1.kmx')] # Execute - uninstall_keyboards_from_gnome([{'id': 'foo1', 'languages': [{'id': 'en'}]}], 'fooDir') + _uninstall_keyboards_from_gnome([{'id': 'foo1', 'languages': [{'id': 'en'}]}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with( [('xkb', 'en')]) @@ -81,7 +81,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [ ('xkb', 'en'), ('ibus', 'fr:fooDir/foo1.kmx')] # Execute - uninstall_keyboards_from_gnome( + _uninstall_keyboards_from_gnome( [{'id': 'foo1', 'languages': [{'id': 'en'}, {'id': 'fr'}]}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with( @@ -93,7 +93,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [ ('xkb', 'en'), ('ibus', 'en:fooDir/foo1.kmx')] # Execute - uninstall_keyboards_from_gnome( + _uninstall_keyboards_from_gnome( [{'id': 'foo1', 'languages': [{'id': 'fr'}]}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with( @@ -105,7 +105,7 @@ class UninstallKmpTests(unittest.TestCase): mockGnomeKeyboardsUtilInstance.read_input_sources.return_value = [ ('xkb', 'en'), ('ibus', 'en:fooDir/foo1.kmx'), ('ibus', 'fr:fooDir/foo1.kmx')] # Execute - uninstall_keyboards_from_gnome( + _uninstall_keyboards_from_gnome( [{'id': 'foo1', 'languages': [{'id': 'fr'}]}], 'fooDir') # Verify mockGnomeKeyboardsUtilInstance.write_input_sources.assert_called_once_with(