Fix 1091 and other minor fixes (#1103)

* Fix 1091

* Update

* flake8

* Only display btrfs options if there is a filesystem

* Fix 1118

Co-authored-by: Daniel Girtler <girtler.daniel@gmail.com>
This commit is contained in:
Daniel Girtler 2022-05-02 21:02:21 +10:00 committed by GitHub
parent f00717ff6f
commit 2d37157178
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 71 additions and 44 deletions

View File

@ -89,7 +89,7 @@ from .text_input import TextInput
from .menu import Menu from .menu import Menu
from os import system from os import system
from copy import copy from copy import copy
from typing import Union, Any, List, TYPE_CHECKING from typing import Union, Any, TYPE_CHECKING, Dict
if TYPE_CHECKING: if TYPE_CHECKING:
_: Any _: Any
@ -149,18 +149,26 @@ class ListManager:
# default values for the null case # default values for the null case
self.target = None self.target = None
self.action = self._null_action self.action = self._null_action
if len(self._data) == 0 and self._null_action: if len(self._data) == 0 and self._null_action:
self.exec_action(self._data) self.exec_action(self._data)
def run(self): def run(self):
while True: while True:
self._data_formatted = self.reformat(self._data) # this will return a dictionary with the key as the menu entry to be displayed
options = self._data_formatted + [self.separator] # and the value is the original value from the self._data container
data_formatted = self.reformat(self._data)
options = list(data_formatted.keys())
options.append(self.separator)
if self._default_action: if self._default_action:
options += self._default_action options += self._default_action
options += self.bottom_list options += self.bottom_list
system('clear') system('clear')
target = Menu(self._prompt, target = Menu(
self._prompt,
options, options,
sort=False, sort=False,
clear_screen=False, clear_screen=False,
@ -171,19 +179,20 @@ class ListManager:
if not target or target in self.bottom_list: if not target or target in self.bottom_list:
self.action = target self.action = target
break break
if target and target == self.separator:
continue
if target and target in self._default_action: if target and target in self._default_action:
self.action = target self.action = target
target = None
self.target = None self.target = None
self.exec_action(self._data) self.exec_action(self._data)
continue continue
if isinstance(self._data,dict): if isinstance(self._data,dict):
key = list(self._data.keys())[self._data_formatted.index(target)] data_key = data_formatted[target]
self.target = {key: self._data[key]} key = self._data[data_key]
self.target = {data_key: key}
else: else:
self.target = self._data[self._data_formatted.index(target)] self.target = self._data[data_formatted[target]]
# Possible enhacement. If run_actions returns false a message line indicating the failure # Possible enhacement. If run_actions returns false a message line indicating the failure
self.run_actions(target) self.run_actions(target)
@ -211,15 +220,15 @@ class ListManager:
The following methods are expected to be overwritten by the user if the needs of the list are beyond the simple case The following methods are expected to be overwritten by the user if the needs of the list are beyond the simple case
""" """
def reformat(self, data: Any) -> List[Any]: def reformat(self, data: Any) -> Dict[str, Any]:
""" """
method to get the data in a format suitable to be shown method to get the data in a format suitable to be shown
It is executed once for run loop and processes the whole self._data structure It is executed once for run loop and processes the whole self._data structure
""" """
if isinstance(data,dict): if isinstance(data,dict):
return list(map(lambda x:f"{x} : {data[x]}",data)) return {f'{k}: {v}': k for k, v in data.items()}
else: else:
return list(map(lambda x:str(x),data)) return {str(k): k for k in data}
def action_list(self): def action_list(self):
""" """

View File

@ -41,13 +41,13 @@ def select_disk_layout(block_devices: list, advanced_options=False) -> Dict[str,
custome_mode = str(_('Select what to do with each individual drive (followed by partition usage)')) custome_mode = str(_('Select what to do with each individual drive (followed by partition usage)'))
modes = [wipe_mode, custome_mode] modes = [wipe_mode, custome_mode]
print(modes) mode = Menu(_('Select what you wish to do with the selected block devices'), modes).run()
mode = Menu(_('Select what you wish to do with the selected block devices'), modes, skip=False).run()
if mode == wipe_mode: if mode:
return get_default_partition_layout(block_devices, advanced_options) if mode == wipe_mode:
else: return get_default_partition_layout(block_devices, advanced_options)
return select_individual_blockdevice_usage(block_devices) else:
return select_individual_blockdevice_usage(block_devices)
def select_disk(dict_o_disks: Dict[str, BlockDevice]) -> BlockDevice: def select_disk(dict_o_disks: Dict[str, BlockDevice]) -> BlockDevice:

View File

@ -36,7 +36,7 @@ class UserList(ListManager):
] ]
super().__init__(prompt, lusers, self.actions, self.actions[0]) super().__init__(prompt, lusers, self.actions, self.actions[0])
def reformat(self, data: Any) -> List[Any]: def reformat(self, data: List) -> Dict:
def format_element(elem :str): def format_element(elem :str):
# secret gives away the length of the password # secret gives away the length of the password
if data[elem].get('!password'): if data[elem].get('!password'):
@ -49,7 +49,7 @@ class UserList(ListManager):
super_user = ' ' super_user = ' '
return f"{elem:16}: password {pwd:16} {super_user}" return f"{elem:16}: password {pwd:16} {super_user}"
return list(map(lambda x: format_element(x), data)) return {format_element(e): e for e in data}
def action_list(self): def action_list(self):
if self.target: if self.target:

View File

@ -65,21 +65,26 @@ def _current_partition_layout(partitions: List[Partition], with_idx: bool = Fals
return f'\n\n{title}:\n\n{current_layout}' return f'\n\n{title}:\n\n{current_layout}'
def select_partition(title :str, partitions :List[Partition], multiple :bool = False, filter :Callable = None) -> Union[int, List[int], None]: def _get_partitions(partitions :List[Partition], filter_ :Callable = None) -> List[str]:
""" """
filter allows to filter out the indexes once they are set. Should return True if element is to be included filter allows to filter out the indexes once they are set. Should return True if element is to be included
""" """
partition_indexes = [] partition_indexes = []
for i in range(len(partitions)): for i in range(len(partitions)):
if filter: if filter_:
if filter(partitions[i]): if filter_(partitions[i]):
partition_indexes.append(str(i)) partition_indexes.append(str(i))
else: else:
partition_indexes.append(str(i)) partition_indexes.append(str(i))
return partition_indexes
def select_partition(title :str, partitions :List[Partition], multiple :bool = False, filter_ :Callable = None) -> Union[int, List[int], None]:
partition_indexes = _get_partitions(partitions, filter_)
if len(partition_indexes) == 0: if len(partition_indexes) == 0:
return None return None
# old code without filter
# partition_indexes = list(map(str, range(len(partitions))))
partition = Menu(title, partition_indexes, multi=multiple).run() partition = Menu(title, partition_indexes, multi=multiple).run()
@ -133,7 +138,7 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
while True: while True:
modes = [new_partition, suggest_partition_layout] modes = [new_partition, suggest_partition_layout]
if len(block_device_struct['partitions']): if len(block_device_struct['partitions']) > 0:
modes += [ modes += [
delete_partition, delete_partition,
delete_all_partitions, delete_all_partitions,
@ -143,9 +148,16 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
mark_bootable, mark_bootable,
mark_compressed, mark_compressed,
set_filesystem_partition, set_filesystem_partition,
set_btrfs_subvolumes,
] ]
indexes = _get_partitions(
block_device_struct["partitions"],
filter_=lambda x: True if x.get('filesystem', {}).get('format') == 'btrfs' else False
)
if len(indexes) > 0:
modes += [set_btrfs_subvolumes]
title = _('Select what to do with\n{}').format(block_device) title = _('Select what to do with\n{}').format(block_device)
# show current partition layout: # show current partition layout:
@ -165,7 +177,10 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
# # https://www.gnu.org/software/parted/manual/html_node/mklabel.html # # https://www.gnu.org/software/parted/manual/html_node/mklabel.html
# name = input("Enter a desired name for the partition: ").strip() # name = input("Enter a desired name for the partition: ").strip()
fstype = Menu(_('Enter a desired filesystem type for the partition'), fs_types(), skip=False).run() fstype = Menu(_('Enter a desired filesystem type for the partition'), fs_types()).run()
if not fstype:
continue
prompt = _('Enter the start sector (percentage or block number, default: {}): ').format( prompt = _('Enter the start sector (percentage or block number, default: {}): ').format(
block_device.first_free_sector) block_device.first_free_sector)
@ -273,14 +288,13 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
if not block_device_struct["partitions"][partition].get('filesystem', None): if not block_device_struct["partitions"][partition].get('filesystem', None):
block_device_struct["partitions"][partition]['filesystem'] = {} block_device_struct["partitions"][partition]['filesystem'] = {}
fstype = Menu(_('Enter a desired filesystem type for the partition'), fs_types(), fstype = Menu(_('Enter a desired filesystem type for the partition'), fs_types()).run()
skip=False).run()
block_device_struct["partitions"][partition]['filesystem']['format'] = fstype if fstype:
block_device_struct["partitions"][partition]['filesystem']['format'] = fstype
# Negate the current wipe marking # Negate the current wipe marking
block_device_struct["partitions"][partition][ block_device_struct["partitions"][partition]['wipe'] = not block_device_struct["partitions"][partition].get('wipe', False)
'wipe'] = not block_device_struct["partitions"][partition].get('wipe', False)
elif task == mark_encrypted: elif task == mark_encrypted:
title = _('{}\n\nSelect which partition to mark as encrypted').format(current_layout) title = _('{}\n\nSelect which partition to mark as encrypted').format(current_layout)
@ -308,16 +322,18 @@ def manage_new_and_existing_partitions(block_device: 'BlockDevice') -> Dict[str,
block_device_struct["partitions"][partition]['filesystem'] = {} block_device_struct["partitions"][partition]['filesystem'] = {}
fstype_title = _('Enter a desired filesystem type for the partition: ') fstype_title = _('Enter a desired filesystem type for the partition: ')
fstype = Menu(fstype_title, fs_types(), skip=False).run() fstype = Menu(fstype_title, fs_types()).run()
block_device_struct["partitions"][partition]['filesystem']['format'] = fstype if fstype:
block_device_struct["partitions"][partition]['filesystem']['format'] = fstype
elif task == set_btrfs_subvolumes: elif task == set_btrfs_subvolumes:
from .subvolume_config import SubvolumeList from .subvolume_config import SubvolumeList
# TODO get preexisting partitions # TODO get preexisting partitions
title = _('{}\n\nSelect which partition to set subvolumes on').format(current_layout) title = _('{}\n\nSelect which partition to set subvolumes on').format(current_layout)
partition = select_partition(title, block_device_struct["partitions"],filter=lambda x:True if x.get('filesystem',{}).get('format') == 'btrfs' else False) partition = select_partition(title, block_device_struct["partitions"],filter_=lambda x:True if x.get('filesystem',{}).get('format') == 'btrfs' else False)
if partition is not None: if partition is not None:
if not block_device_struct["partitions"][partition].get('btrfs', {}): if not block_device_struct["partitions"][partition].get('btrfs', {}):
block_device_struct["partitions"][partition]['btrfs'] = {} block_device_struct["partitions"][partition]['btrfs'] = {}

View File

@ -1,9 +1,10 @@
from typing import List, Any, Dict from typing import Any, Dict
from ..menu.list_manager import ListManager from ..menu.list_manager import ListManager
from ..menu.selection_menu import Selector, GeneralMenu from ..menu.selection_menu import Selector, GeneralMenu
from ..menu.text_input import TextInput from ..menu.text_input import TextInput
from ..menu import Menu from ..menu import Menu
""" """
UI classes UI classes
""" """
@ -14,7 +15,7 @@ class SubvolumeList(ListManager):
self.ObjectDefaultAction = str(_('Add')) self.ObjectDefaultAction = str(_('Add'))
super().__init__(prompt,list,None,self.ObjectNullAction,self.ObjectDefaultAction) super().__init__(prompt,list,None,self.ObjectNullAction,self.ObjectDefaultAction)
def reformat(self, data: Any) -> List[Any]: def reformat(self, data: Dict) -> Dict:
def presentation(key :str, value :Dict): def presentation(key :str, value :Dict):
text = _(" Subvolume :{:16}").format(key) text = _(" Subvolume :{:16}").format(key)
if isinstance(value,str): if isinstance(value,str):
@ -28,14 +29,15 @@ class SubvolumeList(ListManager):
text += _(" with option {}").format(', '.join(value['options'])) text += _(" with option {}").format(', '.join(value['options']))
return text return text
return sorted(list(map(lambda x:presentation(x,data[x]),data))) formatted = {presentation(k, v): k for k, v in data.items()}
return {k: v for k, v in sorted(formatted.items(), key=lambda e: e[0])}
def action_list(self): def action_list(self):
return super().action_list() return super().action_list()
def exec_action(self, data: Any): def exec_action(self, data: Dict):
if self.target: if self.target:
origkey,origval = list(self.target.items())[0] origkey, origval = list(self.target.items())[0]
else: else:
origkey = None origkey = None
@ -46,8 +48,8 @@ class SubvolumeList(ListManager):
self.target = {} self.target = {}
print(_('\n Fill the desired values for a new subvolume \n')) print(_('\n Fill the desired values for a new subvolume \n'))
with SubvolumeMenu(self.target,self.action) as add_menu: with SubvolumeMenu(self.target,self.action) as add_menu:
for data in ['name','mountpoint','options']: for elem in ['name','mountpoint','options']:
add_menu.exec_option(data) add_menu.exec_option(elem)
else: else:
SubvolumeMenu(self.target,self.action).run() SubvolumeMenu(self.target,self.action).run()