Specify menu return types using generics instead of Any (#3400)
This commit is contained in:
parent
fae210dfea
commit
0de90bd55b
|
|
@ -68,7 +68,7 @@ class DesktopProfile(Profile):
|
|||
group = MenuItemGroup(items, sort_items=True, sort_case_sensitive=False)
|
||||
group.set_selected_by_value(self.current_selection)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[Profile](
|
||||
group,
|
||||
multi=True,
|
||||
allow_reset=True,
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class HyprlandProfile(XorgProfile):
|
|||
default = self.custom_settings.get('seat_access', None)
|
||||
group.set_default_by_value(default)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[SeatAccess](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=False,
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ class LabwcProfile(XorgProfile):
|
|||
default = self.custom_settings.get('seat_access', None)
|
||||
group.set_default_by_value(default)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[SeatAccess](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=False,
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ class NiriProfile(XorgProfile):
|
|||
default = self.custom_settings.get('seat_access', None)
|
||||
group.set_default_by_value(default)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[SeatAccess](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=False,
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ class SwayProfile(XorgProfile):
|
|||
default = self.custom_settings.get('seat_access', None)
|
||||
group.set_default_by_value(default)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[SeatAccess](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=False,
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ class ServerProfile(Profile):
|
|||
group = MenuItemGroup(items, sort_items=True)
|
||||
group.set_selected_by_value(self.current_selection)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[Profile](
|
||||
group,
|
||||
allow_reset=True,
|
||||
allow_skip=True,
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ class ConfigurationOutput:
|
|||
group.focus_item = MenuItem.yes()
|
||||
group.set_preview_for_all(lambda x: self.user_config_to_json())
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -168,7 +168,7 @@ def save_config(config: ArchConfig) -> None:
|
|||
]
|
||||
|
||||
group = MenuItemGroup(items)
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
allow_skip=True,
|
||||
preview_frame=FrameProperties.max(str(_('Configuration'))),
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class DiskMenuConfig:
|
|||
lvm_config: LvmConfiguration | None
|
||||
|
||||
|
||||
class DiskLayoutConfigurationMenu(AbstractSubMenu):
|
||||
class DiskLayoutConfigurationMenu(AbstractSubMenu[DiskLayoutConfiguration]):
|
||||
def __init__(self, disk_layout_config: DiskLayoutConfiguration | None):
|
||||
if not disk_layout_config:
|
||||
self._disk_menu_config = DiskMenuConfig(disk_config=None, lvm_config=None)
|
||||
|
|
@ -101,7 +101,7 @@ class DiskLayoutConfigurationMenu(AbstractSubMenu):
|
|||
if not item.value:
|
||||
return None
|
||||
|
||||
disk_layout_conf: DiskLayoutConfiguration = item.get_value()
|
||||
disk_layout_conf = item.get_value()
|
||||
|
||||
if disk_layout_conf.config_type == DiskLayoutType.Pre_mount:
|
||||
msg = str(_('Configuration type: {}')).format(disk_layout_conf.config_type.display_msg()) + '\n'
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class DiskEncryptionMenu(AbstractSubMenu):
|
||||
class DiskEncryptionMenu(AbstractSubMenu[DiskEncryption]):
|
||||
def __init__(
|
||||
self,
|
||||
disk_config: DiskLayoutConfiguration,
|
||||
|
|
@ -233,7 +233,7 @@ def select_encryption_type(disk_config: DiskLayoutConfiguration, preset: Encrypt
|
|||
group = MenuItemGroup(items)
|
||||
group.set_focus_by_value(preset_value)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[EncryptionType](
|
||||
group,
|
||||
allow_skip=True,
|
||||
allow_reset=True,
|
||||
|
|
@ -273,7 +273,7 @@ def select_hsm(preset: Fido2Device | None = None) -> Fido2Device | None:
|
|||
group, table_header = MenuHelper.create_table(data=fido_devices)
|
||||
header = f'{header}\n\n{table_header}'
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[Fido2Device](
|
||||
group,
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -309,7 +309,7 @@ def select_partitions_to_encrypt(
|
|||
if avail_partitions:
|
||||
group, header = MenuHelper.create_table(data=avail_partitions)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[PartitionModification](
|
||||
group,
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -337,7 +337,7 @@ def select_lvm_vols_to_encrypt(
|
|||
if volumes:
|
||||
group, header = MenuHelper.create_table(data=volumes)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[LvmVolume](
|
||||
group,
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
|
|||
|
|
@ -77,7 +77,7 @@ class DiskSegment:
|
|||
return data
|
||||
|
||||
|
||||
class PartitioningList(ListManager):
|
||||
class PartitioningList(ListManager[DiskSegment]):
|
||||
def __init__(
|
||||
self,
|
||||
device_mod: DeviceModification,
|
||||
|
|
@ -438,7 +438,7 @@ class PartitioningList(ListManager):
|
|||
items = [MenuItem(fs.value, value=fs) for fs in fs_types]
|
||||
group = MenuItemGroup(items, sort_items=False)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[FilesystemType](
|
||||
group,
|
||||
header=prompt,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -509,7 +509,7 @@ class PartitioningList(ListManager):
|
|||
|
||||
title = str(_('Size (default: {}): ')).format(max_size.format_highest())
|
||||
|
||||
result = EditMenu(
|
||||
result = EditMenu[str](
|
||||
title,
|
||||
header=f'{prompt}\b',
|
||||
allow_skip=True,
|
||||
|
|
@ -564,7 +564,7 @@ class PartitioningList(ListManager):
|
|||
def _reset_confirmation(self) -> bool:
|
||||
prompt = str(_('This will remove all newly added partitions, continue?')) + '\n'
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
MenuItemGroup.yes_no(),
|
||||
header=prompt,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class SubvolumeMenu(ListManager):
|
||||
class SubvolumeMenu(ListManager[SubvolumeModification]):
|
||||
def __init__(
|
||||
self,
|
||||
btrfs_subvols: list[SubvolumeModification],
|
||||
|
|
@ -41,7 +41,7 @@ class SubvolumeMenu(ListManager):
|
|||
return str(selection.name)
|
||||
|
||||
def _add_subvolume(self, preset: SubvolumeModification | None = None) -> SubvolumeModification | None:
|
||||
result = EditMenu(
|
||||
result = EditMenu[str](
|
||||
str(_('Subvolume name')),
|
||||
alignment=Alignment.CENTER,
|
||||
allow_skip=True,
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class GlobalMenu(AbstractMenu):
|
||||
class GlobalMenu(AbstractMenu[None]):
|
||||
def __init__(self, arch_config: ArchConfig) -> None:
|
||||
self._arch_config = arch_config
|
||||
menu_optioons = self._get_menu_options()
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ if TYPE_CHECKING:
|
|||
|
||||
def select_devices(preset: list[BDevice] | None = []) -> list[BDevice]:
|
||||
def _preview_device_selection(item: MenuItem) -> str | None:
|
||||
device: _DeviceInfo = item.get_value()
|
||||
device = item.get_value()
|
||||
dev = device_handler.get_device(device.path)
|
||||
|
||||
if dev and dev.partition_infos:
|
||||
|
|
@ -64,7 +64,7 @@ def select_devices(preset: list[BDevice] | None = []) -> list[BDevice]:
|
|||
group.set_selected_by_value(presets)
|
||||
group.set_preview_for_all(_preview_device_selection)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[_DeviceInfo](
|
||||
group,
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -82,7 +82,7 @@ def select_devices(preset: list[BDevice] | None = []) -> list[BDevice]:
|
|||
case ResultType.Skip:
|
||||
return preset
|
||||
case ResultType.Selection:
|
||||
selected_device_info: list[_DeviceInfo] = result.get_values()
|
||||
selected_device_info = result.get_values()
|
||||
selected_devices = []
|
||||
|
||||
for device in devices:
|
||||
|
|
@ -140,7 +140,7 @@ def select_disk_config(preset: DiskLayoutConfiguration | None = None) -> DiskLay
|
|||
if preset:
|
||||
group.set_selected_by_value(preset.config_type.display_msg())
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
allow_skip=True,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -210,7 +210,7 @@ def select_lvm_config(
|
|||
group = MenuItemGroup(items)
|
||||
group.set_focus_by_value(preset_value)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
allow_reset=True,
|
||||
allow_skip=True,
|
||||
|
|
@ -261,7 +261,7 @@ def select_main_filesystem_format() -> FilesystemType:
|
|||
items.append(MenuItem('ntfs', value=FilesystemType.Ntfs))
|
||||
|
||||
group = MenuItemGroup(items, sort_items=False)
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[FilesystemType](
|
||||
group,
|
||||
alignment=Alignment.CENTER,
|
||||
frame=FrameProperties.min('Filesystem'),
|
||||
|
|
@ -285,7 +285,7 @@ def select_mount_options() -> list[str]:
|
|||
MenuItem(disable_cow, value=BtrfsMountOption.nodatacow.value),
|
||||
]
|
||||
group = MenuItemGroup(items, sort_items=False)
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
header=prompt,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -336,7 +336,7 @@ def suggest_single_disk_layout(
|
|||
prompt = str(_('Would you like to use BTRFS subvolumes with a default structure?')) + '\n'
|
||||
group = MenuItemGroup.yes_no()
|
||||
group.set_focus_by_value(MenuItem.yes().value)
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=prompt,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -577,7 +577,7 @@ def suggest_lvm_layout(
|
|||
group = MenuItemGroup.yes_no()
|
||||
group.set_focus_by_value(MenuItem.yes().value)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=prompt,
|
||||
search_enabled=False,
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ def ask_ntp(preset: bool = True) -> bool:
|
|||
group = MenuItemGroup.yes_no()
|
||||
group.focus_item = preset_val
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=True,
|
||||
|
|
@ -61,7 +61,7 @@ def ask_ntp(preset: bool = True) -> bool:
|
|||
|
||||
|
||||
def ask_hostname(preset: str | None = None) -> str | None:
|
||||
result = EditMenu(
|
||||
result = EditMenu[str](
|
||||
str(_('Hostname')),
|
||||
alignment=Alignment.CENTER,
|
||||
allow_skip=True,
|
||||
|
|
@ -89,7 +89,7 @@ def ask_for_a_timezone(preset: str | None = None) -> str | None:
|
|||
group.set_selected_by_value(preset)
|
||||
group.set_default_by_value(default)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
allow_reset=True,
|
||||
allow_skip=True,
|
||||
|
|
@ -113,7 +113,7 @@ def ask_for_audio_selection(preset: AudioConfiguration | None = None) -> AudioCo
|
|||
if preset:
|
||||
group.set_focus_by_value(preset.audio)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[Audio](
|
||||
group,
|
||||
allow_skip=True,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -156,7 +156,7 @@ def select_archinstall_language(languages: list[Language], preset: Language) ->
|
|||
title += 'All available fonts can be found in "/usr/share/kbd/consolefonts"\n'
|
||||
title += 'e.g. setfont LatGrkCyr-8x16 (to display latin/greek/cyrillic characters)\n'
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[Language](
|
||||
group,
|
||||
header=title,
|
||||
allow_skip=True,
|
||||
|
|
@ -215,7 +215,7 @@ def ask_additional_packages_to_install(
|
|||
menu_group = MenuItemGroup(items, sort_items=True)
|
||||
menu_group.set_selected_by_value(preset_packages)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[AvailablePackage | PackageGroup](
|
||||
menu_group,
|
||||
header=header,
|
||||
alignment=Alignment.LEFT,
|
||||
|
|
@ -233,7 +233,7 @@ def ask_additional_packages_to_install(
|
|||
case ResultType.Reset:
|
||||
return []
|
||||
case ResultType.Selection:
|
||||
selected_pacakges: list[AvailablePackage | PackageGroup] = result.get_values()
|
||||
selected_pacakges = result.get_values()
|
||||
return [pkg.name for pkg in selected_pacakges]
|
||||
|
||||
|
||||
|
|
@ -255,7 +255,7 @@ def add_number_of_parallel_downloads(preset: int | None = None) -> int | None:
|
|||
|
||||
return str(_('Invalid download number'))
|
||||
|
||||
result = EditMenu(
|
||||
result = EditMenu[str](
|
||||
str(_('Number downloads')),
|
||||
header=header,
|
||||
allow_skip=True,
|
||||
|
|
@ -295,7 +295,7 @@ def ask_post_installation() -> PostInstallationAction:
|
|||
items = [MenuItem(action.value, value=action) for action in PostInstallationAction]
|
||||
group = MenuItemGroup(items)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[PostInstallationAction](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=False,
|
||||
|
|
@ -313,7 +313,7 @@ def ask_abort() -> None:
|
|||
prompt = str(_('Do you really want to abort?')) + '\n'
|
||||
group = MenuItemGroup.yes_no()
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=prompt,
|
||||
allow_skip=False,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class UserList(ListManager):
|
||||
class UserList(ListManager[User]):
|
||||
def __init__(self, prompt: str, lusers: list[User]):
|
||||
self._actions = [
|
||||
str(_('Add a user')),
|
||||
|
|
@ -70,7 +70,7 @@ class UserList(ListManager):
|
|||
return str(_("The username you entered is invalid"))
|
||||
|
||||
def _add_user(self) -> User | None:
|
||||
editResult = EditMenu(
|
||||
editResult = EditMenu[str](
|
||||
str(_('Username')),
|
||||
allow_skip=True,
|
||||
validator=self._check_for_correct_username
|
||||
|
|
@ -97,7 +97,7 @@ class UserList(ListManager):
|
|||
group = MenuItemGroup.yes_no()
|
||||
group.focus_item = MenuItem.yes()
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class ManualNetworkConfig(ListManager):
|
||||
class ManualNetworkConfig(ListManager[Nic]):
|
||||
def __init__(self, prompt: str, preset: list[Nic]):
|
||||
self._actions = [
|
||||
str(_('Add interface')),
|
||||
|
|
@ -70,7 +70,7 @@ class ManualNetworkConfig(ListManager):
|
|||
items = [MenuItem(i, value=i) for i in available]
|
||||
group = MenuItemGroup(items, sort_items=True)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
alignment=Alignment.CENTER,
|
||||
frame=FrameProperties.min(str(_('Interfaces'))),
|
||||
|
|
@ -106,7 +106,7 @@ class ManualNetworkConfig(ListManager):
|
|||
except ValueError:
|
||||
return str(_('You need to enter a valid IP in IP-config mode'))
|
||||
|
||||
result = EditMenu(
|
||||
result = EditMenu[str](
|
||||
title,
|
||||
header=header,
|
||||
validator=validator,
|
||||
|
|
@ -132,7 +132,7 @@ class ManualNetworkConfig(ListManager):
|
|||
group = MenuItemGroup(items, sort_items=True)
|
||||
group.set_default_by_value(default_mode)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=False,
|
||||
|
|
@ -192,7 +192,7 @@ def ask_to_configure_network(preset: NetworkConfiguration | None) -> NetworkConf
|
|||
if preset:
|
||||
group.set_selected_by_value(preset.type)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[NetworkConfiguration](
|
||||
group,
|
||||
alignment=Alignment.CENTER,
|
||||
frame=FrameProperties.min(str(_('Network configuration'))),
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ def select_kernel(preset: list[str] = []) -> list[str]:
|
|||
group.set_focus_by_value(default_kernel)
|
||||
group.set_selected_by_value(preset)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
allow_skip=True,
|
||||
allow_reset=True,
|
||||
|
|
@ -69,7 +69,7 @@ def ask_for_bootloader(preset: Bootloader | None) -> Bootloader | None:
|
|||
group.set_default_by_value(default)
|
||||
group.set_focus_by_value(preset)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[Bootloader](
|
||||
group,
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -92,7 +92,7 @@ def ask_for_uki(preset: bool = True) -> bool:
|
|||
group = MenuItemGroup.yes_no()
|
||||
group.set_focus_by_value(preset)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=prompt,
|
||||
columns=2,
|
||||
|
|
@ -136,7 +136,7 @@ def select_driver(options: list[GfxDriver] = [], preset: GfxDriver | None = None
|
|||
if SysInfo.has_nvidia_graphics():
|
||||
header += str(_('For the best compatibility with your Nvidia hardware, you may want to use the Nvidia proprietary driver.\n'))
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[GfxDriver](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=True,
|
||||
|
|
@ -166,7 +166,7 @@ def ask_for_swap(preset: bool = True) -> bool:
|
|||
group = MenuItemGroup.yes_no()
|
||||
group.set_focus_by_value(default_item)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=prompt,
|
||||
columns=2,
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class LocaleMenu(AbstractSubMenu):
|
||||
class LocaleMenu(AbstractSubMenu[LocaleConfiguration]):
|
||||
def __init__(
|
||||
self,
|
||||
locale_conf: LocaleConfiguration
|
||||
|
|
@ -85,7 +85,7 @@ def select_locale_lang(preset: str | None = None) -> str | None:
|
|||
group = MenuItemGroup(items, sort_items=True)
|
||||
group.set_focus_by_value(preset)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
alignment=Alignment.CENTER,
|
||||
frame=FrameProperties.min(str(_('Locale language'))),
|
||||
|
|
@ -109,7 +109,7 @@ def select_locale_enc(preset: str | None = None) -> str | None:
|
|||
group = MenuItemGroup(items, sort_items=True)
|
||||
group.set_focus_by_value(preset)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
alignment=Alignment.CENTER,
|
||||
frame=FrameProperties.min(str(_('Locale encoding'))),
|
||||
|
|
@ -141,7 +141,7 @@ def select_kb_layout(preset: str | None = None) -> str | None:
|
|||
group = MenuItemGroup(items, sort_items=False)
|
||||
group.set_focus_by_value(preset)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
alignment=Alignment.CENTER,
|
||||
frame=FrameProperties.min(str(_('Keyboard layout'))),
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ if TYPE_CHECKING:
|
|||
CONFIG_KEY = '__config__'
|
||||
|
||||
|
||||
class AbstractMenu:
|
||||
class AbstractMenu[ValueT]:
|
||||
def __init__(
|
||||
self,
|
||||
item_group: MenuItemGroup,
|
||||
|
|
@ -97,11 +97,11 @@ class AbstractMenu:
|
|||
def _is_config_valid(self) -> bool:
|
||||
return True
|
||||
|
||||
def run(self) -> Any | None:
|
||||
def run(self) -> ValueT | None:
|
||||
self._sync_from_config()
|
||||
|
||||
while True:
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[ValueT](
|
||||
self._menu_item_group,
|
||||
allow_skip=False,
|
||||
allow_reset=self._allow_reset,
|
||||
|
|
@ -126,7 +126,7 @@ class AbstractMenu:
|
|||
return None
|
||||
|
||||
|
||||
class AbstractSubMenu(AbstractMenu):
|
||||
class AbstractSubMenu[ValueT](AbstractMenu[ValueT]):
|
||||
def __init__(
|
||||
self,
|
||||
item_group: MenuItemGroup,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import copy
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import TYPE_CHECKING, Any, cast
|
||||
|
||||
from archinstall.tui.curses_menu import SelectMenu
|
||||
from archinstall.tui.menu_item import MenuItem, MenuItemGroup
|
||||
|
|
@ -16,10 +16,10 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class ListManager:
|
||||
class ListManager[ValueT]:
|
||||
def __init__(
|
||||
self,
|
||||
entries: list[Any],
|
||||
entries: list[ValueT],
|
||||
base_actions: list[str],
|
||||
sub_menu_actions: list[str],
|
||||
prompt: str | None = None
|
||||
|
|
@ -51,10 +51,10 @@ class ListManager:
|
|||
self._base_actions = base_actions
|
||||
self._sub_menu_actions = sub_menu_actions
|
||||
|
||||
self._last_choice: str | None = None
|
||||
self._last_choice: ValueT | str | None = None
|
||||
|
||||
@property
|
||||
def last_choice(self) -> str | None:
|
||||
def last_choice(self) -> ValueT | str | None:
|
||||
return self._last_choice
|
||||
|
||||
def is_last_choice_cancel(self) -> bool:
|
||||
|
|
@ -62,7 +62,7 @@ class ListManager:
|
|||
return self._last_choice == self._cancel_action
|
||||
return False
|
||||
|
||||
def run(self) -> list[Any]:
|
||||
def run(self) -> list[ValueT]:
|
||||
while True:
|
||||
# this will return a dictionary with the key as the menu entry to be displayed
|
||||
# and the value is the original value from the self._data container
|
||||
|
|
@ -77,7 +77,7 @@ class ListManager:
|
|||
items = [MenuItem(o[0], value=o[1]) for o in options]
|
||||
group = MenuItemGroup(items, sort_items=False)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[ValueT | str](
|
||||
group,
|
||||
header=header,
|
||||
search_enabled=False,
|
||||
|
|
@ -92,11 +92,14 @@ class ListManager:
|
|||
raise ValueError('Unhandled return type')
|
||||
|
||||
if value in self._base_actions:
|
||||
value = cast(str, value)
|
||||
self._data = self.handle_action(value, None, self._data)
|
||||
elif value in self._terminate_actions:
|
||||
break
|
||||
else: # an entry of the existing selection was chosen
|
||||
selected_entry = result.get_value()
|
||||
selected_entry = cast(ValueT, selected_entry)
|
||||
|
||||
self._run_actions_on_entry(selected_entry)
|
||||
|
||||
self._last_choice = value
|
||||
|
|
@ -111,7 +114,7 @@ class ListManager:
|
|||
header = '\n'.join(table_header)
|
||||
return header
|
||||
|
||||
def _prepare_selection(self, data_formatted: dict[str, Any]) -> list[tuple[str, Any]]:
|
||||
def _prepare_selection(self, data_formatted: dict[str, Any]) -> list[tuple[str, str | ValueT]]:
|
||||
# header rows are mapped to None so make sure
|
||||
# to exclude those from the selectable data
|
||||
options = [(key, val) for key, val in data_formatted.items() if val is not None]
|
||||
|
|
@ -125,7 +128,7 @@ class ListManager:
|
|||
|
||||
return options
|
||||
|
||||
def _run_actions_on_entry(self, entry: Any) -> None:
|
||||
def _run_actions_on_entry(self, entry: ValueT) -> None:
|
||||
options = self.filter_options(entry, self._sub_menu_actions) + [self._cancel_action]
|
||||
|
||||
items = [MenuItem(o, value=o) for o in options]
|
||||
|
|
@ -133,7 +136,7 @@ class ListManager:
|
|||
|
||||
header = f'{self.selected_action_display(entry)}\n'
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[str](
|
||||
group,
|
||||
header=header,
|
||||
search_enabled=False,
|
||||
|
|
@ -171,21 +174,21 @@ class ListManager:
|
|||
|
||||
return display_data
|
||||
|
||||
def selected_action_display(self, selection: Any) -> str:
|
||||
def selected_action_display(self, selection: ValueT) -> str:
|
||||
"""
|
||||
this will return the value to be displayed in the
|
||||
"Select an action for '{}'" string
|
||||
"""
|
||||
raise NotImplementedError('Please implement me in the child class')
|
||||
|
||||
def handle_action(self, action: Any, entry: Any | None, data: list[Any]) -> list[Any]:
|
||||
def handle_action(self, action: str, entry: ValueT | None, data: list[ValueT]) -> list[ValueT]:
|
||||
"""
|
||||
this function is called when a base action or
|
||||
a specific action for an entry is triggered
|
||||
"""
|
||||
raise NotImplementedError('Please implement me in the child class')
|
||||
|
||||
def filter_options(self, selection: Any, options: list[str]) -> list[str]:
|
||||
def filter_options(self, selection: ValueT, options: list[str]) -> list[str]:
|
||||
"""
|
||||
filter which actions to show for an specific selection
|
||||
"""
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class CustomMirrorRepositoriesList(ListManager):
|
||||
class CustomMirrorRepositoriesList(ListManager[CustomRepository]):
|
||||
def __init__(self, custom_repositories: list[CustomRepository]):
|
||||
self._actions = [
|
||||
str(_('Add a custom repository')),
|
||||
|
|
@ -74,7 +74,7 @@ class CustomMirrorRepositoriesList(ListManager):
|
|||
return data
|
||||
|
||||
def _add_custom_repository(self, preset: CustomRepository | None = None) -> CustomRepository | None:
|
||||
edit_result = EditMenu(
|
||||
edit_result = EditMenu[str](
|
||||
str(_('Repository name')),
|
||||
alignment=Alignment.CENTER,
|
||||
allow_skip=True,
|
||||
|
|
@ -91,7 +91,7 @@ class CustomMirrorRepositoriesList(ListManager):
|
|||
|
||||
header = f'{_("Name")}: {name}'
|
||||
|
||||
edit_result = EditMenu(
|
||||
edit_result = EditMenu[str](
|
||||
str(_('Url')),
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -116,7 +116,7 @@ class CustomMirrorRepositoriesList(ListManager):
|
|||
if preset is not None:
|
||||
group.set_selected_by_value(preset.sign_check.value)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[SignCheck](
|
||||
group,
|
||||
header=prompt,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -154,7 +154,7 @@ class CustomMirrorRepositoriesList(ListManager):
|
|||
return CustomRepository(name, url, sign_check, sign_opt)
|
||||
|
||||
|
||||
class CustomMirrorServersList(ListManager):
|
||||
class CustomMirrorServersList(ListManager[CustomServer]):
|
||||
def __init__(self, custom_servers: list[CustomServer]):
|
||||
self._actions = [
|
||||
str(_('Add a custom server')),
|
||||
|
|
@ -196,7 +196,7 @@ class CustomMirrorServersList(ListManager):
|
|||
return data
|
||||
|
||||
def _add_custom_server(self, preset: CustomServer | None = None) -> CustomServer | None:
|
||||
edit_result = EditMenu(
|
||||
edit_result = EditMenu[str](
|
||||
str(_('Server url')),
|
||||
alignment=Alignment.CENTER,
|
||||
allow_skip=True,
|
||||
|
|
@ -213,7 +213,7 @@ class CustomMirrorServersList(ListManager):
|
|||
return None
|
||||
|
||||
|
||||
class MirrorMenu(AbstractSubMenu):
|
||||
class MirrorMenu(AbstractSubMenu[MirrorConfiguration]):
|
||||
def __init__(
|
||||
self,
|
||||
preset: MirrorConfiguration | None = None
|
||||
|
|
@ -265,7 +265,7 @@ class MirrorMenu(AbstractSubMenu):
|
|||
]
|
||||
|
||||
def _prev_regions(self, item: MenuItem) -> str | None:
|
||||
regions: list[MirrorRegion] = item.get_value()
|
||||
regions = item.get_value()
|
||||
|
||||
output = ''
|
||||
for region in regions:
|
||||
|
|
@ -323,7 +323,7 @@ def select_mirror_regions(preset: list[MirrorRegion]) -> list[MirrorRegion]:
|
|||
|
||||
group.set_selected_by_value(preset_regions)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[MirrorRegion](
|
||||
group,
|
||||
alignment=Alignment.CENTER,
|
||||
frame=FrameProperties.min(str(_('Mirror regions'))),
|
||||
|
|
@ -338,7 +338,7 @@ def select_mirror_regions(preset: list[MirrorRegion]) -> list[MirrorRegion]:
|
|||
case ResultType.Reset:
|
||||
return []
|
||||
case ResultType.Selection:
|
||||
selected_mirrors: list[MirrorRegion] = result.get_values()
|
||||
selected_mirrors = result.get_values()
|
||||
return selected_mirrors
|
||||
|
||||
|
||||
|
|
@ -365,7 +365,7 @@ def select_optional_repositories(preset: list[Repository]) -> list[Repository]:
|
|||
group = MenuItemGroup(items, sort_items=True)
|
||||
group.set_selected_by_value(preset)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[Repository](
|
||||
group,
|
||||
alignment=Alignment.CENTER,
|
||||
frame=FrameProperties.min('Additional repositories'),
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class ProfileMenu(AbstractSubMenu):
|
||||
class ProfileMenu(AbstractSubMenu[ProfileConfiguration]):
|
||||
def __init__(
|
||||
self,
|
||||
preset: ProfileConfiguration | None = None
|
||||
|
|
@ -114,7 +114,7 @@ class ProfileMenu(AbstractSubMenu):
|
|||
group.focus_item = MenuItem.no()
|
||||
group.default_item = MenuItem.no()
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
group,
|
||||
header=header,
|
||||
allow_skip=False,
|
||||
|
|
@ -175,7 +175,7 @@ def select_greeter(
|
|||
|
||||
group.set_default_by_value(default)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[GreeterType](
|
||||
group,
|
||||
allow_skip=True,
|
||||
frame=FrameProperties.min(str(_('Greeter'))),
|
||||
|
|
@ -208,7 +208,7 @@ def select_profile(
|
|||
group = MenuItemGroup(items, sort_items=True)
|
||||
group.set_selected_by_value(current_profile)
|
||||
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[Profile](
|
||||
group,
|
||||
header=header,
|
||||
allow_reset=allow_reset,
|
||||
|
|
@ -223,7 +223,7 @@ def select_profile(
|
|||
case ResultType.Skip:
|
||||
return current_profile
|
||||
case ResultType.Selection:
|
||||
profile_selection: Profile = result.get_value()
|
||||
profile_selection = result.get_value()
|
||||
select_result = profile_selection.do_on_select()
|
||||
|
||||
if not select_result:
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ def get_password(
|
|||
elif header is not None:
|
||||
user_hdr = header
|
||||
|
||||
result = EditMenu(
|
||||
result = EditMenu[str](
|
||||
text,
|
||||
header=user_hdr,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -53,7 +53,7 @@ def get_password(
|
|||
else:
|
||||
confirmation_header = f'{_("Password")}: {password.hidden()}\n'
|
||||
|
||||
result = EditMenu(
|
||||
result = EditMenu[str](
|
||||
str(_('Confirm password')),
|
||||
header=confirmation_header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -87,7 +87,7 @@ def prompt_dir(
|
|||
else:
|
||||
validate_func = None
|
||||
|
||||
result = EditMenu(
|
||||
result = EditMenu[str](
|
||||
text,
|
||||
header=header,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ if TYPE_CHECKING:
|
|||
_: Callable[[str], DeferredTranslation]
|
||||
|
||||
|
||||
class AbstractCurses(metaclass=ABCMeta):
|
||||
class AbstractCurses[ValueT](metaclass=ABCMeta):
|
||||
def __init__(self) -> None:
|
||||
self._help_window = self._set_help_viewport()
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ class AbstractCurses(metaclass=ABCMeta):
|
|||
pass
|
||||
|
||||
@abstractmethod
|
||||
def kickoff(self, win: curses.window) -> Result:
|
||||
def kickoff(self, win: curses.window) -> Result[ValueT]:
|
||||
pass
|
||||
|
||||
def clear_all(self) -> None:
|
||||
|
|
@ -71,7 +71,7 @@ class AbstractCurses(metaclass=ABCMeta):
|
|||
|
||||
def _confirm_interrupt(self, warning: str) -> bool:
|
||||
while True:
|
||||
result = SelectMenu(
|
||||
result = SelectMenu[bool](
|
||||
MenuItemGroup.yes_no(),
|
||||
header=warning,
|
||||
alignment=Alignment.CENTER,
|
||||
|
|
@ -461,7 +461,7 @@ class Viewport(AbstractViewport):
|
|||
self._main_win.refresh()
|
||||
|
||||
|
||||
class EditMenu(AbstractCurses):
|
||||
class EditMenu[ValueT](AbstractCurses[ValueT]):
|
||||
def __init__(
|
||||
self,
|
||||
title: str,
|
||||
|
|
@ -506,7 +506,7 @@ class EditMenu(AbstractCurses):
|
|||
|
||||
self._init_viewports()
|
||||
|
||||
self._last_state: Result | None = None
|
||||
self._last_state: Result[ValueT] | None = None
|
||||
self._help_active = False
|
||||
self._real_input = default_text or ""
|
||||
|
||||
|
|
@ -536,7 +536,7 @@ class EditMenu(AbstractCurses):
|
|||
y_offset += 3
|
||||
self._info_vp = Viewport(self._max_width, 1, 0, y_offset, alignment=self._alignment)
|
||||
|
||||
def input(self) -> Result:
|
||||
def input(self) -> Result[ValueT]:
|
||||
result = Tui.run(self)
|
||||
|
||||
assert not result.has_item() or isinstance(result.text(), str)
|
||||
|
|
@ -593,7 +593,7 @@ class EditMenu(AbstractCurses):
|
|||
self._input_vp.edit(default_text=self._default_text)
|
||||
|
||||
@override
|
||||
def kickoff(self, win: curses.window) -> Result:
|
||||
def kickoff(self, win: curses.window) -> Result[ValueT]:
|
||||
try:
|
||||
self._draw()
|
||||
except KeyboardInterrupt:
|
||||
|
|
@ -680,7 +680,7 @@ class EditMenu(AbstractCurses):
|
|||
return True
|
||||
|
||||
|
||||
class SelectMenu(AbstractCurses):
|
||||
class SelectMenu[ValueT](AbstractCurses[ValueT]):
|
||||
def __init__(
|
||||
self,
|
||||
group: MenuItemGroup,
|
||||
|
|
@ -769,13 +769,13 @@ class SelectMenu(AbstractCurses):
|
|||
|
||||
return offset
|
||||
|
||||
def run(self) -> Result:
|
||||
def run(self) -> Result[ValueT]:
|
||||
result = Tui.run(self)
|
||||
self._clear_all()
|
||||
return result
|
||||
|
||||
@override
|
||||
def kickoff(self, win: curses.window) -> Result:
|
||||
def kickoff(self, win: curses.window) -> Result[ValueT]:
|
||||
self._draw()
|
||||
|
||||
while True:
|
||||
|
|
@ -1137,7 +1137,7 @@ class SelectMenu(AbstractCurses):
|
|||
else:
|
||||
return False
|
||||
|
||||
def _process_input_key(self, key: int) -> Result | None:
|
||||
def _process_input_key(self, key: int) -> Result[ValueT] | None:
|
||||
key_handles = MenuKeys.from_ord(key)
|
||||
|
||||
if self._help_active:
|
||||
|
|
@ -1339,7 +1339,7 @@ class Tui:
|
|||
return self._screen.getmaxyx()
|
||||
|
||||
@staticmethod
|
||||
def run(component: AbstractCurses) -> Result:
|
||||
def run[ValueT](component: AbstractCurses[ValueT]) -> Result[ValueT]:
|
||||
if Tui._t is None:
|
||||
tui = Tui().init()
|
||||
tui.screen.clear()
|
||||
|
|
@ -1355,7 +1355,7 @@ class Tui:
|
|||
if hasattr(self, '_component') and self._component is not None: # pylint: disable=no-member
|
||||
self._component.resize_win() # pylint: disable=no-member
|
||||
|
||||
def _main_loop(self, component: AbstractCurses) -> Result:
|
||||
def _main_loop[ValueT](self, component: AbstractCurses[ValueT]) -> Result[ValueT]:
|
||||
self._screen.refresh()
|
||||
return component.kickoff(self._screen)
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from dataclasses import dataclass
|
||||
from enum import Enum, auto
|
||||
from typing import Any
|
||||
|
||||
from .menu_item import MenuItem
|
||||
|
||||
|
|
@ -12,17 +11,17 @@ class ResultType(Enum):
|
|||
|
||||
|
||||
@dataclass
|
||||
class Result:
|
||||
class Result[ValueT]:
|
||||
type_: ResultType
|
||||
_item: MenuItem | list[MenuItem] | str | None
|
||||
|
||||
def has_item(self) -> bool:
|
||||
return self._item is not None
|
||||
|
||||
def get_value(self) -> Any:
|
||||
return self.item().get_value()
|
||||
def get_value(self) -> ValueT:
|
||||
return self.item().get_value() # type: ignore[no-any-return]
|
||||
|
||||
def get_values(self) -> list[Any]:
|
||||
def get_values(self) -> list[ValueT]:
|
||||
return [i.get_value() for i in self.items()]
|
||||
|
||||
def item(self) -> MenuItem:
|
||||
|
|
|
|||
Loading…
Reference in New Issue