From 6383b5e82ff8c29d29fa4aa64dfc374ade4b1252 Mon Sep 17 00:00:00 2001 From: correctmost <134317971+correctmost@users.noreply.github.com> Date: Sat, 16 Nov 2024 17:49:10 -0500 Subject: [PATCH] Replace Optional with union syntax in scripts/ and tui/ (#2839) --- archinstall/scripts/guided.py | 6 +-- archinstall/scripts/swiss.py | 4 +- archinstall/tui/curses_menu.py | 84 +++++++++++++++++----------------- archinstall/tui/menu_item.py | 34 +++++++------- archinstall/tui/types.py | 4 +- 5 files changed, 68 insertions(+), 64 deletions(-) diff --git a/archinstall/scripts/guided.py b/archinstall/scripts/guided.py index e0052dc5..85bd17d7 100644 --- a/archinstall/scripts/guided.py +++ b/archinstall/scripts/guided.py @@ -1,5 +1,5 @@ from pathlib import Path -from typing import Any, TYPE_CHECKING, Optional +from typing import Any, TYPE_CHECKING import archinstall from archinstall import info, debug @@ -100,7 +100,7 @@ def perform_installation(mountpoint: Path) -> None: # If user selected to copy the current ISO network configuration # Perform a copy of the config - network_config: Optional[NetworkConfiguration] = archinstall.arguments.get('network_config', None) + network_config: NetworkConfiguration | None = archinstall.arguments.get('network_config', None) if network_config: network_config.install_network_config( @@ -111,7 +111,7 @@ def perform_installation(mountpoint: Path) -> None: if users := archinstall.arguments.get('!users', None): installation.create_users(users) - audio_config: Optional[AudioConfiguration] = archinstall.arguments.get('audio_config', None) + audio_config: AudioConfiguration | None = archinstall.arguments.get('audio_config', None) if audio_config: audio_config.install_audio_config(installation) else: diff --git a/archinstall/scripts/swiss.py b/archinstall/scripts/swiss.py index 930c7632..a00a0f35 100644 --- a/archinstall/scripts/swiss.py +++ b/archinstall/scripts/swiss.py @@ -1,6 +1,6 @@ from enum import Enum from pathlib import Path -from typing import TYPE_CHECKING, Any, Optional +from typing import TYPE_CHECKING, Any import archinstall from archinstall import SysInfo, info, debug @@ -184,7 +184,7 @@ def perform_installation(mountpoint: Path, exec_mode: ExecutionMode) -> None: if users := archinstall.arguments.get('!users', None): installation.create_users(users) - audio_config: Optional[AudioConfiguration] = archinstall.arguments.get('audio_config', None) + audio_config: AudioConfiguration | None = archinstall.arguments.get('audio_config', None) if audio_config: audio_config.install_audio_config(installation) else: diff --git a/archinstall/tui/curses_menu.py b/archinstall/tui/curses_menu.py index e1d49358..59ece5d8 100644 --- a/archinstall/tui/curses_menu.py +++ b/archinstall/tui/curses_menu.py @@ -1,3 +1,5 @@ +from __future__ import annotations + import sys import curses import dataclasses @@ -9,7 +11,7 @@ from collections.abc import Callable from curses.textpad import Textbox from dataclasses import dataclass from types import FrameType, TracebackType -from typing import Any, Optional, TYPE_CHECKING, Literal +from typing import Any, TYPE_CHECKING, Literal from .help import Help from .menu_item import MenuItem, MenuItemGroup @@ -93,7 +95,7 @@ class AbstractCurses(metaclass=ABCMeta): def get_header_entries( self, - header: Optional[str], + header: str | None, offset: int = 0 ) -> list[ViewportEntry]: cur_row = 0 @@ -125,7 +127,7 @@ class AbstractViewport: max_width: int, max_height: int, frame: FrameProperties, - scroll_pct: Optional[int] = None + scroll_pct: int | None = None ) -> list[ViewportEntry]: if not entries: return [] @@ -164,7 +166,7 @@ class AbstractViewport: def _get_right_frame( self, dim: _FrameDim, - scroll_percentage: Optional[int] = None + scroll_percentage: int | None = None ) -> list[ViewportEntry]: right_frame = {} scroll_height = int(dim.height * scroll_percentage // 100) if scroll_percentage else 0 @@ -189,7 +191,7 @@ class AbstractViewport: dim: _FrameDim, h_bar: str, frame: FrameProperties, - scroll_percentage: Optional[int] = None + scroll_percentage: int | None = None ) -> ViewportEntry: top = self._replace_str(h_bar, 1, f' {frame.header} ') if frame.header else h_bar @@ -204,7 +206,7 @@ class AbstractViewport: self, dim: _FrameDim, h_bar: str, - scroll_pct: Optional[int] = None + scroll_pct: int | None = None ) -> ViewportEntry: if scroll_pct is None: bottom = Chars.Lower_left + h_bar + Chars.Lower_right @@ -293,7 +295,7 @@ class EditViewport(AbstractViewport): edit_height: int, x_start: int, y_start: int, - process_key: Callable[[int], Optional[int]], + process_key: Callable[[int], int | None], frame: FrameProperties, alignment: Alignment = Alignment.CENTER, hide_input: bool = False @@ -312,9 +314,9 @@ class EditViewport(AbstractViewport): self._alignment = alignment self._hide_input = hide_input - self._main_win: Optional['curses._CursesWindow'] = None - self._edit_win: Optional['curses._CursesWindow'] = None - self._textbox: Optional[Textbox] = None + self._main_win: 'curses._CursesWindow | None' = None + self._edit_win: 'curses._CursesWindow | None' = None + self._textbox: Textbox | None = None self._init_wins() @@ -366,7 +368,7 @@ class EditViewport(AbstractViewport): self._main_win.erase() self._main_win.refresh() - def edit(self, default_text: Optional[str] = None) -> None: + def edit(self, default_text: str | None = None) -> None: assert self._edit_win and self._main_win self._edit_win.erase() @@ -387,8 +389,8 @@ class EditViewport(AbstractViewport): class ViewportState: cur_pos: int displayed_entries: list[ViewportEntry] - scroll_pct: Optional[int] - scroll_pos: Optional[int] = 0 + scroll_pct: int | None + scroll_pos: int | None = 0 def offset(self) -> int: return min([entry.row for entry in self.displayed_entries], default=0) @@ -409,7 +411,7 @@ class Viewport(AbstractViewport): x_start: int, y_start: int, enable_scroll: bool = False, - frame: Optional[FrameProperties] = None, + frame: FrameProperties | None = None, alignment: Alignment = Alignment.LEFT ): super().__init__() @@ -426,7 +428,7 @@ class Viewport(AbstractViewport): self._main_win.nodelay(False) self._main_win.standout() - self._state: Optional[ViewportState] = None + self._state: ViewportState | None = None def getch(self) -> int: return self._main_win.getch() @@ -439,7 +441,7 @@ class Viewport(AbstractViewport): self, lines: list[ViewportEntry], cur_pos: int = 0, - scroll_pos: Optional[int] = None + scroll_pos: int | None = None ) -> None: self._state = self._get_viewport_state(lines, cur_pos, scroll_pos) visible_entries = self._adjust_entries_row(self._state.displayed_entries) @@ -478,7 +480,7 @@ class Viewport(AbstractViewport): self, total: int, available_rows: int, scroll_pos: int - ) -> Optional[int]: + ) -> int | None: if total <= available_rows: return None @@ -493,7 +495,7 @@ class Viewport(AbstractViewport): self, entries: list[ViewportEntry], cur_pos: int, - scroll_pos: Optional[int] = 0 + scroll_pos: int | None = 0 ) -> ViewportState: if not entries: return ViewportState(cur_pos, [], 0) @@ -539,7 +541,7 @@ class Viewport(AbstractViewport): entries: list[ViewportEntry], cur_pos: int, screen_rows: int, - scroll_pos: Optional[int], + scroll_pos: int | None, total_rows: int ) -> list[ViewportEntry]: if scroll_pos is not None: @@ -595,13 +597,13 @@ class EditMenu(AbstractCurses): self, title: str, edit_width: int = 50, - header: Optional[str] = None, - validator: Optional[Callable[[str], Optional[str]]] = None, + header: str | None = None, + validator: Callable[[str], str | None] | None = None, allow_skip: bool = False, allow_reset: bool = False, - reset_warning_msg: Optional[str] = None, + reset_warning_msg: str | None = None, alignment: Alignment = Alignment.CENTER, - default_text: Optional[str] = None, + default_text: str | None = None, hide_input: bool = False ): super().__init__() @@ -625,14 +627,14 @@ class EditMenu(AbstractCurses): title = f'* {title}' if not self._allow_skip else title self._frame = FrameProperties(title, FrameStyle.MAX) - self._help_vp: Optional[Viewport] = None - self._header_vp: Optional[Viewport] = None - self._input_vp: Optional[EditViewport] = None - self._error_vp: Optional[Viewport] = None + self._help_vp: Viewport | None = None + self._header_vp: Viewport | None = None + self._input_vp: EditViewport | None = None + self._error_vp: Viewport | None = None self._init_viewports() - self._last_state: Optional[Result] = None + self._last_state: Result | None = None self._help_active = False self._real_input = "" @@ -683,7 +685,7 @@ class EditMenu(AbstractCurses): if self._error_vp: self._error_vp.erase() - def _get_input_text(self) -> Optional[str]: + def _get_input_text(self) -> str | None: assert self._input_vp assert self._error_vp @@ -737,7 +739,7 @@ class EditMenu(AbstractCurses): return self._last_state - def _process_edit_key(self, key: int) -> Optional[int]: + def _process_edit_key(self, key: int) -> int | None: key_handles = MenuKeys.from_ord(key) if self._help_active: @@ -812,10 +814,10 @@ class SelectMenu(AbstractCurses): search_enabled: bool = True, allow_skip: bool = False, allow_reset: bool = False, - reset_warning_msg: Optional[str] = None, + reset_warning_msg: str | None = None, preview_style: PreviewStyle = PreviewStyle.NONE, preview_size: float | Literal['auto'] = 0.2, - preview_frame: Optional[FrameProperties] = None, + preview_frame: FrameProperties | None = None, ): super().__init__() @@ -850,16 +852,16 @@ class SelectMenu(AbstractCurses): self._row_entries: list[list[MenuCell]] = [] self._prev_scroll_pos: int = 0 - self._cur_pos: Optional[int] = None + self._cur_pos: int | None = None self._visible_entries: list[ViewportEntry] = [] self._max_height, self._max_width = Tui.t().max_yx - self._help_vp: Optional[Viewport] = None - self._header_vp: Optional[Viewport] = None - self._footer_vp: Optional[Viewport] = None - self._menu_vp: Optional[Viewport] = None - self._preview_vp: Optional[Viewport] = None + self._help_vp: Viewport | None = None + self._header_vp: Viewport | None = None + self._footer_vp: Viewport | None = None + self._menu_vp: Viewport | None = None + self._preview_vp: Viewport | None = None self._init_viewports(preview_size) @@ -1218,7 +1220,7 @@ class SelectMenu(AbstractCurses): return True - def _process_input_key(self, key: int) -> Optional[Result]: + def _process_input_key(self, key: int) -> Result | None: key_handles = MenuKeys.from_ord(key) if self._help_active: @@ -1356,7 +1358,7 @@ class SelectMenu(AbstractCurses): class Tui: - _t: Optional['Tui'] = None + _t: Tui | None = None def __enter__(self) -> None: if Tui._t is None: @@ -1424,7 +1426,7 @@ class Tui: text: str, row: int = 0, col: int = 0, - endl: Optional[str] = '\n', + endl: str | None = '\n', clear_screen: bool = False ) -> None: if Tui._t is None: diff --git a/archinstall/tui/menu_item.py b/archinstall/tui/menu_item.py index 9cdc1d9b..8e1475e1 100644 --- a/archinstall/tui/menu_item.py +++ b/archinstall/tui/menu_item.py @@ -1,6 +1,8 @@ +from __future__ import annotations + from collections.abc import Callable from dataclasses import dataclass, field -from typing import Any, Optional, TYPE_CHECKING +from typing import Any, TYPE_CHECKING from typing import ClassVar from ..lib.output import unicode_ljust @@ -12,18 +14,18 @@ if TYPE_CHECKING: @dataclass class MenuItem: text: str - value: Optional[Any] = None - action: Optional[Callable[[Any], Any]] = None + value: Any | None = None + action: Callable[[Any], Any] | None = None enabled: bool = True mandatory: bool = False dependencies: list[str | Callable[[], bool]] = field(default_factory=list) dependencies_not: list[str] = field(default_factory=list) - display_action: Optional[Callable[[Any], str]] = None - preview_action: Optional[Callable[[Any], Optional[str]]] = None - key: Optional[str] = None + display_action: Callable[[Any], str] | None = None + preview_action: Callable[[Any], str | None] | None = None + key: str | None = None - _yes: ClassVar[Optional['MenuItem']] = None - _no: ClassVar[Optional['MenuItem']] = None + _yes: ClassVar[MenuItem | None] = None + _no: ClassVar[MenuItem | None] = None def get_value(self) -> Any: assert self.value is not None @@ -56,7 +58,7 @@ class MenuItem: else: return True - def get_display_value(self) -> Optional[str]: + def get_display_value(self) -> str | None: if self.display_action is not None: return self.display_action(self.value) @@ -66,8 +68,8 @@ class MenuItem: @dataclass class MenuItemGroup: menu_items: list[MenuItem] - focus_item: Optional[MenuItem] = None - default_item: Optional[MenuItem] = None + focus_item: MenuItem | None = None + default_item: MenuItem | None = None selected_items: list[MenuItem] = field(default_factory=list) sort_items: bool = False checkmarks: bool = False @@ -104,7 +106,7 @@ class MenuItemGroup: sort_items=True ) - def set_preview_for_all(self, action: Callable[[Any], Optional[str]]) -> None: + def set_preview_for_all(self, action: Callable[[Any], str | None]) -> None: for item in self.items: item.preview_action = action @@ -120,7 +122,7 @@ class MenuItemGroup: self.default_item = item break - def set_selected_by_value(self, values: Optional[Any | list[Any]]) -> None: + def set_selected_by_value(self, values: Any | list[Any] | None) -> None: if values is None: return @@ -247,7 +249,7 @@ class MenuItemGroup: else: return item == self.focus_item - def _first(self, items: list[MenuItem], ignore_empty: bool) -> Optional[MenuItem]: + def _first(self, items: list[MenuItem], ignore_empty: bool) -> MenuItem | None: for item in items: if not ignore_empty: return item @@ -257,10 +259,10 @@ class MenuItemGroup: return None - def get_first_item(self, ignore_empty: bool = True) -> Optional[MenuItem]: + def get_first_item(self, ignore_empty: bool = True) -> MenuItem | None: return self._first(self.items, ignore_empty) - def get_last_item(self, ignore_empty: bool = True) -> Optional[MenuItem]: + def get_last_item(self, ignore_empty: bool = True) -> MenuItem | None: items = self.items rev_items = list(reversed(items)) return self._first(rev_items, ignore_empty) diff --git a/archinstall/tui/types.py b/archinstall/tui/types.py index 07c59cf4..f45d87ce 100644 --- a/archinstall/tui/types.py +++ b/archinstall/tui/types.py @@ -1,7 +1,7 @@ import curses from dataclasses import dataclass from enum import Enum, auto -from typing import Optional, Any +from typing import Any from .menu_item import MenuItem @@ -139,7 +139,7 @@ class Chars: @dataclass class Result: type_: ResultType - _item: Optional[MenuItem | list[MenuItem] | str] + _item: MenuItem | list[MenuItem] | str | None def has_item(self) -> bool: return self._item is not None