From 06eadb31d4f0bca0c8cb95b6a9eb62ddd2d7cff2 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Mon, 5 Jun 2023 18:02:49 +1000 Subject: Move locales and cleanup menu (#1814) * Cleanup imports and unused code * Cleanup imports and unused code * Update build check * Keep deprecation exception * Simplify logging * Move locale into new sub-menu --------- Co-authored-by: Daniel Girtler --- archinstall/lib/locale/__init__.py | 6 ++ archinstall/lib/locale/locale.py | 68 +++++++++++++++ archinstall/lib/locale/locale_menu.py | 155 ++++++++++++++++++++++++++++++++++ 3 files changed, 229 insertions(+) create mode 100644 archinstall/lib/locale/__init__.py create mode 100644 archinstall/lib/locale/locale.py create mode 100644 archinstall/lib/locale/locale_menu.py (limited to 'archinstall/lib/locale') diff --git a/archinstall/lib/locale/__init__.py b/archinstall/lib/locale/__init__.py new file mode 100644 index 00000000..6c32d6f3 --- /dev/null +++ b/archinstall/lib/locale/__init__.py @@ -0,0 +1,6 @@ +from .locale_menu import LocaleConfiguration +from .locale import ( + list_keyboard_languages, list_locales, list_x11_keyboard_languages, + verify_keyboard_layout, verify_x11_keyboard_layout, set_kb_layout, + list_timezones +) diff --git a/archinstall/lib/locale/locale.py b/archinstall/lib/locale/locale.py new file mode 100644 index 00000000..c3294e83 --- /dev/null +++ b/archinstall/lib/locale/locale.py @@ -0,0 +1,68 @@ +from typing import Iterator, List + +from ..exceptions import ServiceException, SysCallError +from ..general import SysCommand +from ..output import error + + +def list_keyboard_languages() -> Iterator[str]: + for line in SysCommand("localectl --no-pager list-keymaps", environment_vars={'SYSTEMD_COLORS': '0'}): + yield line.decode('UTF-8').strip() + + +def list_locales() -> List[str]: + with open('/etc/locale.gen', 'r') as fp: + locales = [] + # before the list of locales begins there's an empty line with a '#' in front + # so we'll collect the localels from bottom up and halt when we're donw + entries = fp.readlines() + entries.reverse() + + for entry in entries: + text = entry.replace('#', '').strip() + if text == '': + break + locales.append(text) + + locales.reverse() + return locales + + +def list_x11_keyboard_languages() -> Iterator[str]: + for line in SysCommand("localectl --no-pager list-x11-keymap-layouts", environment_vars={'SYSTEMD_COLORS': '0'}): + yield line.decode('UTF-8').strip() + + +def verify_keyboard_layout(layout :str) -> bool: + for language in list_keyboard_languages(): + if layout.lower() == language.lower(): + return True + return False + + +def verify_x11_keyboard_layout(layout :str) -> bool: + for language in list_x11_keyboard_languages(): + if layout.lower() == language.lower(): + return True + return False + + +def set_kb_layout(locale :str) -> bool: + if len(locale.strip()): + if not verify_keyboard_layout(locale): + error(f"Invalid keyboard locale specified: {locale}") + return False + + try: + SysCommand(f'localectl set-keymap {locale}') + except SysCallError as err: + raise ServiceException(f"Unable to set locale '{locale}' for console: {err}") + + return True + + return False + + +def list_timezones() -> Iterator[str]: + for line in SysCommand("timedatectl --no-pager list-timezones", environment_vars={'SYSTEMD_COLORS': '0'}): + yield line.decode('UTF-8').strip() diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py new file mode 100644 index 00000000..29dd775d --- /dev/null +++ b/archinstall/lib/locale/locale_menu.py @@ -0,0 +1,155 @@ +from dataclasses import dataclass +from typing import Dict, Any, TYPE_CHECKING, Optional + +from .locale import set_kb_layout, list_keyboard_languages, list_locales +from ..menu import Selector, AbstractSubMenu, MenuSelectionType, Menu + +if TYPE_CHECKING: + _: Any + + +@dataclass +class LocaleConfiguration: + kb_layout: str + sys_lang: str + sys_enc: str + + @staticmethod + def default() -> 'LocaleConfiguration': + return LocaleConfiguration('us', 'en_US', 'UTF-8') + + def json(self) -> Dict[str, str]: + return { + 'kb_layout': self.kb_layout, + 'sys_lang': self.sys_lang, + 'sys_enc': self.sys_enc + } + + @classmethod + def _load_config(cls, config: 'LocaleConfiguration', args: Dict[str, Any]) -> 'LocaleConfiguration': + if 'sys_lang' in args: + config.sys_lang = args['sys_lang'] + if 'sys_enc' in args: + config.sys_enc = args['sys_enc'] + if 'kb_layout' in args: + config.kb_layout = args['kb_layout'] + + return config + + @classmethod + def parse_arg(cls, args: Dict[str, Any]) -> 'LocaleConfiguration': + default = cls.default() + + if 'locale_config' in args: + default = cls._load_config(default, args['locale_config']) + else: + default = cls._load_config(default, args) + + return default + + +class LocaleMenu(AbstractSubMenu): + def __init__( + self, + data_store: Dict[str, Any], + locele_conf: LocaleConfiguration + ): + self._preset = locele_conf + super().__init__(data_store=data_store) + + def setup_selection_menu_options(self): + self._menu_options['keyboard-layout'] = \ + Selector( + _('Keyboard layout'), + lambda preset: self._select_kb_layout(preset), + default='us', + enabled=True) + self._menu_options['sys-language'] = \ + Selector( + _('Locale language'), + lambda preset: select_locale_lang(preset), + default='en_US', + enabled=True) + self._menu_options['sys-encoding'] = \ + Selector( + _('Locale encoding'), + lambda preset: select_locale_enc(preset), + default='UTF-8', + enabled=True) + + def run(self, allow_reset: bool = True) -> LocaleConfiguration: + super().run(allow_reset=allow_reset) + + return LocaleConfiguration( + self._data_store['keyboard-layout'], + self._data_store['sys-language'], + self._data_store['sys-encoding'] + ) + + def _select_kb_layout(self, preset: Optional[str]) -> Optional[str]: + kb_lang = select_kb_layout(preset) + if kb_lang: + set_kb_layout(kb_lang) + return kb_lang + + +def select_locale_lang(preset: Optional[str] = None) -> Optional[str]: + locales = list_locales() + locale_lang = set([locale.split()[0] for locale in locales]) + + choice = Menu( + _('Choose which locale language to use'), + list(locale_lang), + sort=True, + preset_values=preset + ).run() + + match choice.type_: + case MenuSelectionType.Selection: return choice.single_value + case MenuSelectionType.Skip: return preset + + return None + + +def select_locale_enc(preset: Optional[str] = None) -> Optional[str]: + locales = list_locales() + locale_enc = set([locale.split()[1] for locale in locales]) + + choice = Menu( + _('Choose which locale encoding to use'), + list(locale_enc), + sort=True, + preset_values=preset + ).run() + + match choice.type_: + case MenuSelectionType.Selection: return choice.single_value + case MenuSelectionType.Skip: return preset + + return None + + +def select_kb_layout(preset: Optional[str] = None) -> Optional[str]: + """ + Asks the user to select a language + Usually this is combined with :ref:`archinstall.list_keyboard_languages`. + + :return: The language/dictionary key of the selected language + :rtype: str + """ + kb_lang = list_keyboard_languages() + # sort alphabetically and then by length + sorted_kb_lang = sorted(sorted(list(kb_lang)), key=len) + + choice = Menu( + _('Select keyboard layout'), + sorted_kb_lang, + preset_values=preset, + sort=False + ).run() + + match choice.type_: + case MenuSelectionType.Skip: return preset + case MenuSelectionType.Selection: return choice.single_value + + return None -- cgit v1.2.3-70-g09d2 From 33d084f16a9055df0327930abe43f7b91429cf24 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 19 Sep 2023 16:51:20 -0400 Subject: Use `SUPPORTED` file for locale options (#2069) * Use `SUPPORTED` file for locale options * Add glibc to `PKGBUILD` depends --- PKGBUILD | 1 + archinstall/lib/locale/locale.py | 23 ++++++++--------------- 2 files changed, 9 insertions(+), 15 deletions(-) (limited to 'archinstall/lib/locale') diff --git a/PKGBUILD b/PKGBUILD index 315256e3..c332d043 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -16,6 +16,7 @@ depends=( 'coreutils' 'cryptsetup' 'e2fsprogs' + 'glibc' 'kbd' 'pciutils' 'procps-ng' diff --git a/archinstall/lib/locale/locale.py b/archinstall/lib/locale/locale.py index c3294e83..90f20cc6 100644 --- a/archinstall/lib/locale/locale.py +++ b/archinstall/lib/locale/locale.py @@ -11,21 +11,14 @@ def list_keyboard_languages() -> Iterator[str]: def list_locales() -> List[str]: - with open('/etc/locale.gen', 'r') as fp: - locales = [] - # before the list of locales begins there's an empty line with a '#' in front - # so we'll collect the localels from bottom up and halt when we're donw - entries = fp.readlines() - entries.reverse() - - for entry in entries: - text = entry.replace('#', '').strip() - if text == '': - break - locales.append(text) - - locales.reverse() - return locales + locales = [] + + with open('/usr/share/i18n/SUPPORTED') as file: + for line in file: + if line != 'C.UTF-8 UTF-8\n': + locales.append(line.rstrip()) + + return locales def list_x11_keyboard_languages() -> Iterator[str]: -- cgit v1.2.3-70-g09d2 From b1e00687953de168bbc31ea435b2c5bdc7c61e39 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Wed, 20 Sep 2023 02:04:23 -0400 Subject: Use `_preset` for defaults in `LocaleMenu` (#2071) * Use `_preset` for defaults in `LocaleMenu` * Fix adjacent typos --- archinstall/lib/locale/locale_menu.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'archinstall/lib/locale') diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py index 29dd775d..2e254315 100644 --- a/archinstall/lib/locale/locale_menu.py +++ b/archinstall/lib/locale/locale_menu.py @@ -52,9 +52,9 @@ class LocaleMenu(AbstractSubMenu): def __init__( self, data_store: Dict[str, Any], - locele_conf: LocaleConfiguration + locale_conf: LocaleConfiguration ): - self._preset = locele_conf + self._preset = locale_conf super().__init__(data_store=data_store) def setup_selection_menu_options(self): @@ -62,19 +62,19 @@ class LocaleMenu(AbstractSubMenu): Selector( _('Keyboard layout'), lambda preset: self._select_kb_layout(preset), - default='us', + default=self._preset.kb_layout, enabled=True) self._menu_options['sys-language'] = \ Selector( _('Locale language'), lambda preset: select_locale_lang(preset), - default='en_US', + default=self._preset.sys_lang, enabled=True) self._menu_options['sys-encoding'] = \ Selector( _('Locale encoding'), lambda preset: select_locale_enc(preset), - default='UTF-8', + default=self._preset.sys_enc, enabled=True) def run(self, allow_reset: bool = True) -> LocaleConfiguration: -- cgit v1.2.3-70-g09d2 From 5c903df55fac449baae1e9cc23b04f6beeb55364 Mon Sep 17 00:00:00 2001 From: Daniel Girtler Date: Mon, 2 Oct 2023 21:01:23 +1100 Subject: Simplify SysCommand decoding (#2121) --- archinstall/lib/disk/device_handler.py | 17 ++++----- archinstall/lib/disk/device_model.py | 11 +++--- archinstall/lib/disk/fido.py | 7 +--- archinstall/lib/general.py | 13 +++++-- archinstall/lib/installer.py | 23 +++++------ archinstall/lib/locale.py | 61 ----------------------------- archinstall/lib/locale/__init__.py | 12 ++++-- archinstall/lib/locale/locale.py | 61 ----------------------------- archinstall/lib/locale/locale_menu.py | 2 +- archinstall/lib/locale/utils.py | 70 ++++++++++++++++++++++++++++++++++ archinstall/lib/luks.py | 2 +- archinstall/lib/packages/packages.py | 2 +- 12 files changed, 117 insertions(+), 164 deletions(-) delete mode 100644 archinstall/lib/locale.py delete mode 100644 archinstall/lib/locale/locale.py create mode 100644 archinstall/lib/locale/utils.py (limited to 'archinstall/lib/locale') diff --git a/archinstall/lib/disk/device_handler.py b/archinstall/lib/disk/device_handler.py index 6927671d..baed2f6f 100644 --- a/archinstall/lib/disk/device_handler.py +++ b/archinstall/lib/disk/device_handler.py @@ -154,20 +154,19 @@ class DeviceHandler(object): mountpoint = Path(common_prefix) try: - result = SysCommand(f'btrfs subvolume list {mountpoint}') + result = SysCommand(f'btrfs subvolume list {mountpoint}').decode() except SysCallError as err: debug(f'Failed to read btrfs subvolume information: {err}') return subvol_infos try: - if decoded := result.decode('utf-8'): - # ID 256 gen 16 top level 5 path @ - for line in decoded.splitlines(): - # expected output format: - # ID 257 gen 8 top level 5 path @home - name = Path(line.split(' ')[-1]) - sub_vol_mountpoint = lsblk_info.btrfs_subvol_info.get(name, None) - subvol_infos.append(_BtrfsSubvolumeInfo(name, sub_vol_mountpoint)) + # ID 256 gen 16 top level 5 path @ + for line in result.splitlines(): + # expected output format: + # ID 257 gen 8 top level 5 path @home + name = Path(line.split(' ')[-1]) + sub_vol_mountpoint = lsblk_info.btrfs_subvol_info.get(name, None) + subvol_infos.append(_BtrfsSubvolumeInfo(name, sub_vol_mountpoint)) except json.decoder.JSONDecodeError as err: error(f"Could not decode lsblk JSON: {result}") raise err diff --git a/archinstall/lib/disk/device_model.py b/archinstall/lib/disk/device_model.py index 26169485..4ac53b0c 100644 --- a/archinstall/lib/disk/device_model.py +++ b/archinstall/lib/disk/device_model.py @@ -1111,12 +1111,12 @@ def _fetch_lsblk_info(dev_path: Optional[Union[Path, str]] = None, retry: int = for retry_attempt in range(retry): try: - result = SysCommand(f'lsblk --json -b -o+{lsblk_fields} {dev_path}') + result = SysCommand(f'lsblk --json -b -o+{lsblk_fields} {dev_path}').decode() break except SysCallError as err: # Get the output minus the message/info from lsblk if it returns a non-zero exit code. if err.worker: - err_str = err.worker.decode('UTF-8') + err_str = err.worker.decode() debug(f'Error calling lsblk: {err_str}') else: raise err @@ -1127,10 +1127,9 @@ def _fetch_lsblk_info(dev_path: Optional[Union[Path, str]] = None, retry: int = time.sleep(1) try: - if decoded := result.decode('utf-8'): - block_devices = json.loads(decoded) - blockdevices = block_devices['blockdevices'] - return [LsblkInfo.from_json(device) for device in blockdevices] + block_devices = json.loads(result) + blockdevices = block_devices['blockdevices'] + return [LsblkInfo.from_json(device) for device in blockdevices] except json.decoder.JSONDecodeError as err: error(f"Could not decode lsblk JSON: {result}") raise err diff --git a/archinstall/lib/disk/fido.py b/archinstall/lib/disk/fido.py index 9eeba56a..49904c17 100644 --- a/archinstall/lib/disk/fido.py +++ b/archinstall/lib/disk/fido.py @@ -2,7 +2,7 @@ from __future__ import annotations import getpass from pathlib import Path -from typing import List, Optional +from typing import List from .device_model import PartitionModification, Fido2Device from ..general import SysCommand, SysCommandWorker, clear_vt100_escape_codes @@ -38,14 +38,11 @@ class Fido2: # down moving the cursor in the menu if not cls._loaded or reload: try: - ret: Optional[str] = SysCommand("systemd-cryptenroll --fido2-device=list").decode('UTF-8') + ret = SysCommand("systemd-cryptenroll --fido2-device=list").decode() except SysCallError: error('fido2 support is most likely not installed') raise ValueError('HSM devices can not be detected, is libfido2 installed?') - if not ret: - return [] - fido_devices: str = clear_vt100_escape_codes(ret) # type: ignore manufacturer_pos = 0 diff --git a/archinstall/lib/general.py b/archinstall/lib/general.py index 71981fb6..3697cf2d 100644 --- a/archinstall/lib/general.py +++ b/archinstall/lib/general.py @@ -430,10 +430,15 @@ class SysCommand: return True - def decode(self, *args, **kwargs) -> Optional[str]: - if self.session: - return self.session._trace_log.decode(*args, **kwargs) - return None + def decode(self, encoding: str = 'utf-8', errors='backslashreplace', strip: bool = True) -> str: + if not self.session: + raise ValueError('No session available to decode') + + val = self.session._trace_log.decode(encoding, errors=errors) + + if strip: + return val.strip() + return val @property def exit_code(self) -> Optional[int]: diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 585389ed..ad98d9a8 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -131,7 +131,7 @@ class Installer: We need to wait for it before we continue since we opted in to use a custom mirror/region. """ info('Waiting for time sync (systemd-timesyncd.service) to complete.') - while SysCommand('timedatectl show --property=NTPSynchronized --value').decode().rstrip() != 'yes': + while SysCommand('timedatectl show --property=NTPSynchronized --value').decode() != 'yes': time.sleep(1) info('Waiting for automatic mirror selection (reflector) to complete.') @@ -282,7 +282,7 @@ class Installer: if enable_resume: resume_uuid = SysCommand(f'findmnt -no UUID -T {self.target}{file}').decode('UTF-8').strip() - resume_offset = SysCommand(f'/usr/bin/filefrag -v {self.target}{file}').decode('UTF-8').split('0:', 1)[1].split(":", 1)[1].split("..", 1)[0].strip() + resume_offset = SysCommand(f'/usr/bin/filefrag -v {self.target}{file}').decode().split('0:', 1)[1].split(":", 1)[1].split("..", 1)[0].strip() self._hooks.append('resume') self._kernel_params.append(f'resume=UUID={resume_uuid}') @@ -312,9 +312,6 @@ class Installer: except SysCallError as err: raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n Error: {err}') - if not gen_fstab: - raise RequirementError(f'Generating fstab returned empty value') - with open(fstab_path, 'a') as fp: fp.write(gen_fstab) @@ -1318,17 +1315,21 @@ TIMEOUT=5 if os.path.splitext(service_name)[1] not in ('.service', '.target', '.timer'): service_name += '.service' # Just to be safe - last_execution_time = b''.join(SysCommand(f"systemctl show --property=ActiveEnterTimestamp --no-pager {service_name}", environment_vars={'SYSTEMD_COLORS': '0'})) - last_execution_time = last_execution_time.lstrip(b'ActiveEnterTimestamp=').strip() + last_execution_time = SysCommand( + f"systemctl show --property=ActiveEnterTimestamp --no-pager {service_name}", + environment_vars={'SYSTEMD_COLORS': '0'} + ).decode().lstrip('ActiveEnterTimestamp=') + if not last_execution_time: return None - return last_execution_time.decode('UTF-8') + return last_execution_time def _service_state(self, service_name: str) -> str: if os.path.splitext(service_name)[1] not in ('.service', '.target', '.timer'): service_name += '.service' # Just to be safe - state = b''.join(SysCommand(f'systemctl show --no-pager -p SubState --value {service_name}', environment_vars={'SYSTEMD_COLORS': '0'})) - - return state.strip().decode('UTF-8') + return SysCommand( + f'systemctl show --no-pager -p SubState --value {service_name}', + environment_vars={'SYSTEMD_COLORS': '0'} + ).decode() diff --git a/archinstall/lib/locale.py b/archinstall/lib/locale.py deleted file mode 100644 index ab158984..00000000 --- a/archinstall/lib/locale.py +++ /dev/null @@ -1,61 +0,0 @@ -from itertools import takewhile -from pathlib import Path -from typing import Iterator, List - -from .exceptions import ServiceException, SysCallError -from .general import SysCommand -from .output import error - - -def list_keyboard_languages() -> Iterator[str]: - for line in SysCommand("localectl --no-pager list-keymaps", environment_vars={'SYSTEMD_COLORS': '0'}): - yield line.decode('UTF-8').strip() - - -def list_locales() -> List[str]: - entries = Path('/etc/locale.gen').read_text().splitlines() - # Before the list of locales begins there's an empty line with a '#' in front - # so we'll collect the locales from bottom up and halt when we're done. - locales = list(takewhile(bool, map(lambda entry: entry.strip('\n\t #'), reversed(entries)))) - locales.reverse() - return locales - - -def list_x11_keyboard_languages() -> Iterator[str]: - for line in SysCommand("localectl --no-pager list-x11-keymap-layouts", environment_vars={'SYSTEMD_COLORS': '0'}): - yield line.decode('UTF-8').strip() - - -def verify_keyboard_layout(layout :str) -> bool: - for language in list_keyboard_languages(): - if layout.lower() == language.lower(): - return True - return False - - -def verify_x11_keyboard_layout(layout :str) -> bool: - for language in list_x11_keyboard_languages(): - if layout.lower() == language.lower(): - return True - return False - - -def set_keyboard_language(locale :str) -> bool: - if len(locale.strip()): - if not verify_keyboard_layout(locale): - error(f"Invalid keyboard locale specified: {locale}") - return False - - try: - SysCommand(f'localectl set-keymap {locale}') - except SysCallError as err: - raise ServiceException(f"Unable to set locale '{locale}' for console: {err}") - - return True - - return False - - -def list_timezones() -> Iterator[str]: - for line in SysCommand("timedatectl --no-pager list-timezones", environment_vars={'SYSTEMD_COLORS': '0'}): - yield line.decode('UTF-8').strip() diff --git a/archinstall/lib/locale/__init__.py b/archinstall/lib/locale/__init__.py index 6c32d6f3..90f1aecc 100644 --- a/archinstall/lib/locale/__init__.py +++ b/archinstall/lib/locale/__init__.py @@ -1,6 +1,10 @@ from .locale_menu import LocaleConfiguration -from .locale import ( - list_keyboard_languages, list_locales, list_x11_keyboard_languages, - verify_keyboard_layout, verify_x11_keyboard_layout, set_kb_layout, - list_timezones +from .utils import ( + list_keyboard_languages, + list_locales, + list_x11_keyboard_languages, + verify_keyboard_layout, + verify_x11_keyboard_layout, + list_timezones, + set_kb_layout ) diff --git a/archinstall/lib/locale/locale.py b/archinstall/lib/locale/locale.py deleted file mode 100644 index 90f20cc6..00000000 --- a/archinstall/lib/locale/locale.py +++ /dev/null @@ -1,61 +0,0 @@ -from typing import Iterator, List - -from ..exceptions import ServiceException, SysCallError -from ..general import SysCommand -from ..output import error - - -def list_keyboard_languages() -> Iterator[str]: - for line in SysCommand("localectl --no-pager list-keymaps", environment_vars={'SYSTEMD_COLORS': '0'}): - yield line.decode('UTF-8').strip() - - -def list_locales() -> List[str]: - locales = [] - - with open('/usr/share/i18n/SUPPORTED') as file: - for line in file: - if line != 'C.UTF-8 UTF-8\n': - locales.append(line.rstrip()) - - return locales - - -def list_x11_keyboard_languages() -> Iterator[str]: - for line in SysCommand("localectl --no-pager list-x11-keymap-layouts", environment_vars={'SYSTEMD_COLORS': '0'}): - yield line.decode('UTF-8').strip() - - -def verify_keyboard_layout(layout :str) -> bool: - for language in list_keyboard_languages(): - if layout.lower() == language.lower(): - return True - return False - - -def verify_x11_keyboard_layout(layout :str) -> bool: - for language in list_x11_keyboard_languages(): - if layout.lower() == language.lower(): - return True - return False - - -def set_kb_layout(locale :str) -> bool: - if len(locale.strip()): - if not verify_keyboard_layout(locale): - error(f"Invalid keyboard locale specified: {locale}") - return False - - try: - SysCommand(f'localectl set-keymap {locale}') - except SysCallError as err: - raise ServiceException(f"Unable to set locale '{locale}' for console: {err}") - - return True - - return False - - -def list_timezones() -> Iterator[str]: - for line in SysCommand("timedatectl --no-pager list-timezones", environment_vars={'SYSTEMD_COLORS': '0'}): - yield line.decode('UTF-8').strip() diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py index 2e254315..729b3b6e 100644 --- a/archinstall/lib/locale/locale_menu.py +++ b/archinstall/lib/locale/locale_menu.py @@ -1,7 +1,7 @@ from dataclasses import dataclass from typing import Dict, Any, TYPE_CHECKING, Optional -from .locale import set_kb_layout, list_keyboard_languages, list_locales +from .utils import list_keyboard_languages, list_locales, set_kb_layout from ..menu import Selector, AbstractSubMenu, MenuSelectionType, Menu if TYPE_CHECKING: diff --git a/archinstall/lib/locale/utils.py b/archinstall/lib/locale/utils.py new file mode 100644 index 00000000..330ca0ce --- /dev/null +++ b/archinstall/lib/locale/utils.py @@ -0,0 +1,70 @@ +from typing import Iterator, List + +from ..exceptions import ServiceException, SysCallError +from ..general import SysCommand +from ..output import error + + +def list_keyboard_languages() -> Iterator[str]: + for line in SysCommand( + "localectl --no-pager list-keymaps", + environment_vars={'SYSTEMD_COLORS': '0'} + ).decode(): + yield line + + +def list_locales() -> List[str]: + locales = [] + + with open('/usr/share/i18n/SUPPORTED') as file: + for line in file: + if line != 'C.UTF-8 UTF-8\n': + locales.append(line.rstrip()) + + return locales + + +def list_x11_keyboard_languages() -> Iterator[str]: + for line in SysCommand( + "localectl --no-pager list-x11-keymap-layouts", + environment_vars={'SYSTEMD_COLORS': '0'} + ).decode(): + yield line + + +def verify_keyboard_layout(layout :str) -> bool: + for language in list_keyboard_languages(): + if layout.lower() == language.lower(): + return True + return False + + +def verify_x11_keyboard_layout(layout :str) -> bool: + for language in list_x11_keyboard_languages(): + if layout.lower() == language.lower(): + return True + return False + + +def set_kb_layout(locale :str) -> bool: + if len(locale.strip()): + if not verify_keyboard_layout(locale): + error(f"Invalid keyboard locale specified: {locale}") + return False + + try: + SysCommand(f'localectl set-keymap {locale}') + except SysCallError as err: + raise ServiceException(f"Unable to set locale '{locale}' for console: {err}") + + return True + + return False + + +def list_timezones() -> Iterator[str]: + for line in SysCommand( + "timedatectl --no-pager list-timezones", + environment_vars={'SYSTEMD_COLORS': '0'} + ).decode(): + yield line diff --git a/archinstall/lib/luks.py b/archinstall/lib/luks.py index 84b0e6fd..ea09ae7c 100644 --- a/archinstall/lib/luks.py +++ b/archinstall/lib/luks.py @@ -116,7 +116,7 @@ class Luks2: command = f'/usr/bin/cryptsetup luksUUID {self.luks_dev_path}' try: - return SysCommand(command).decode().strip() # type: ignore + return SysCommand(command).decode() except SysCallError as err: info(f'Unable to get UUID for Luks device: {self.luks_dev_path}') raise err diff --git a/archinstall/lib/packages/packages.py b/archinstall/lib/packages/packages.py index b71b0ce8..7491df07 100644 --- a/archinstall/lib/packages/packages.py +++ b/archinstall/lib/packages/packages.py @@ -37,7 +37,7 @@ def group_search(name :str) -> List[PackageSearchResult]: raise err # Just to be sure some code didn't slip through the exception - data = response.read().decode('UTF-8') + data = response.read().decode('utf-8') return [PackageSearchResult(**package) for package in json.loads(data)['results']] -- cgit v1.2.3-70-g09d2 From dc69acd4b43931f9fd3a267d78834d1a38fbb10f Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Mon, 9 Oct 2023 06:40:59 -0400 Subject: Fix keyboard layout and timezone menus (#2153) --- archinstall/lib/interactions/general_conf.py | 4 ++-- archinstall/lib/locale/locale_menu.py | 2 +- archinstall/lib/locale/utils.py | 23 ++++++++++------------- 3 files changed, 13 insertions(+), 16 deletions(-) (limited to 'archinstall/lib/locale') diff --git a/archinstall/lib/interactions/general_conf.py b/archinstall/lib/interactions/general_conf.py index 56598e25..a23426d0 100644 --- a/archinstall/lib/interactions/general_conf.py +++ b/archinstall/lib/interactions/general_conf.py @@ -44,7 +44,7 @@ def ask_for_a_timezone(preset: Optional[str] = None) -> Optional[str]: choice = Menu( _('Select a timezone'), - list(timezones), + timezones, preset_values=preset, default_option=default ).run() @@ -95,7 +95,7 @@ def select_language(preset: Optional[str] = None) -> Optional[str]: """ kb_lang = list_keyboard_languages() # sort alphabetically and then by length - sorted_kb_lang = sorted(sorted(list(kb_lang)), key=len) + sorted_kb_lang = sorted(kb_lang, key=lambda x: (len(x), x)) choice = Menu( _('Select keyboard layout'), diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py index 729b3b6e..75cc1332 100644 --- a/archinstall/lib/locale/locale_menu.py +++ b/archinstall/lib/locale/locale_menu.py @@ -139,7 +139,7 @@ def select_kb_layout(preset: Optional[str] = None) -> Optional[str]: """ kb_lang = list_keyboard_languages() # sort alphabetically and then by length - sorted_kb_lang = sorted(sorted(list(kb_lang)), key=len) + sorted_kb_lang = sorted(kb_lang, key=lambda x: (len(x), x)) choice = Menu( _('Select keyboard layout'), diff --git a/archinstall/lib/locale/utils.py b/archinstall/lib/locale/utils.py index 330ca0ce..d7641d50 100644 --- a/archinstall/lib/locale/utils.py +++ b/archinstall/lib/locale/utils.py @@ -1,16 +1,15 @@ -from typing import Iterator, List +from typing import List from ..exceptions import ServiceException, SysCallError from ..general import SysCommand from ..output import error -def list_keyboard_languages() -> Iterator[str]: - for line in SysCommand( +def list_keyboard_languages() -> List[str]: + return SysCommand( "localectl --no-pager list-keymaps", environment_vars={'SYSTEMD_COLORS': '0'} - ).decode(): - yield line + ).decode().splitlines() def list_locales() -> List[str]: @@ -24,12 +23,11 @@ def list_locales() -> List[str]: return locales -def list_x11_keyboard_languages() -> Iterator[str]: - for line in SysCommand( +def list_x11_keyboard_languages() -> List[str]: + return SysCommand( "localectl --no-pager list-x11-keymap-layouts", environment_vars={'SYSTEMD_COLORS': '0'} - ).decode(): - yield line + ).decode().splitlines() def verify_keyboard_layout(layout :str) -> bool: @@ -62,9 +60,8 @@ def set_kb_layout(locale :str) -> bool: return False -def list_timezones() -> Iterator[str]: - for line in SysCommand( +def list_timezones() -> List[str]: + return SysCommand( "timedatectl --no-pager list-timezones", environment_vars={'SYSTEMD_COLORS': '0'} - ).decode(): - yield line + ).decode().splitlines() -- cgit v1.2.3-70-g09d2 From 332ec0d6236ca863cb6a2101849555935066549f Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 17 Oct 2023 05:21:39 -0400 Subject: Fix reset in locales menu (#2178) --- archinstall/lib/locale/locale_menu.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'archinstall/lib/locale') diff --git a/archinstall/lib/locale/locale_menu.py b/archinstall/lib/locale/locale_menu.py index 75cc1332..db119f20 100644 --- a/archinstall/lib/locale/locale_menu.py +++ b/archinstall/lib/locale/locale_menu.py @@ -80,6 +80,9 @@ class LocaleMenu(AbstractSubMenu): def run(self, allow_reset: bool = True) -> LocaleConfiguration: super().run(allow_reset=allow_reset) + if not self._data_store: + return LocaleConfiguration.default() + return LocaleConfiguration( self._data_store['keyboard-layout'], self._data_store['sys-language'], -- cgit v1.2.3-70-g09d2