Fix import and configuration loading issues (#1764)

* Fix import and configuration loading issues

* Fix mypy

---------

Co-authored-by: Daniel Girtler <girtler.daniel@gmail.com>
This commit is contained in:
Daniel Girtler 2023-04-22 16:04:36 +10:00 committed by GitHub
parent 00b0ae7ba4
commit 32982b880b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 245 additions and 246 deletions

View File

@ -4,7 +4,7 @@ from argparse import ArgumentParser, Namespace
from .lib import disk from .lib import disk
from .lib import menu from .lib import menu
from .lib import models as models from .lib import models
from .lib import packages from .lib import packages
from .lib.exceptions import * from .lib.exceptions import *
@ -203,17 +203,17 @@ def load_config():
storage['_selected_servers'] = arguments.get('servers', None) storage['_selected_servers'] = arguments.get('servers', None)
if arguments.get('nic', None) is not None: if arguments.get('nic', None) is not None:
handler = NetworkConfigurationHandler() handler = models.NetworkConfigurationHandler()
handler.parse_arguments(arguments.get('nic')) handler.parse_arguments(arguments.get('nic'))
arguments['nic'] = handler.configuration arguments['nic'] = handler.configuration
if arguments.get('!users', None) is not None or arguments.get('!superusers', None) is not None: if arguments.get('!users', None) is not None or arguments.get('!superusers', None) is not None:
users = arguments.get('!users', None) users = arguments.get('!users', None)
superusers = arguments.get('!superusers', None) superusers = arguments.get('!superusers', None)
arguments['!users'] = User.parse_arguments(users, superusers) arguments['!users'] = models.User.parse_arguments(users, superusers)
if arguments.get('bootloader', None) is not None: if arguments.get('bootloader', None) is not None:
arguments['bootloader'] = Bootloader.from_arg(arguments['bootloader']) arguments['bootloader'] = models.Bootloader.from_arg(arguments['bootloader'])
if arguments.get('disk_encryption', None) is not None and disk_config is not None: if arguments.get('disk_encryption', None) is not None and disk_config is not None:
password = arguments.get('encryption_password', '') password = arguments.get('encryption_password', '')

View File

@ -1,218 +1,218 @@
from typing import List, Dict, Optional, TYPE_CHECKING, Any # from typing import List, Dict, Optional, TYPE_CHECKING, Any
#
from ..lib import menu # from ..lib import menu
from archinstall.lib.output import log, FormattedOutput # from archinstall.lib.output import log, FormattedOutput
from archinstall.lib.profile.profiles_handler import profile_handler # from archinstall.lib.profile.profiles_handler import profile_handler
from archinstall.default_profiles.profile import Profile, ProfileType, SelectResult, ProfileInfo, TProfile # from archinstall.default_profiles.profile import Profile, ProfileType, SelectResult, ProfileInfo, TProfile
#
if TYPE_CHECKING: # if TYPE_CHECKING:
from archinstall.lib.installer import Installer # from archinstall.lib.installer import Installer
_: Any # _: Any
#
#
class CustomProfileList(menu.ListManager): # class CustomProfileList(menu.ListManager):
def __init__(self, prompt: str, profiles: List[TProfile]): # def __init__(self, prompt: str, profiles: List[TProfile]):
self._actions = [ # self._actions = [
str(_('Add profile')), # str(_('Add profile')),
str(_('Edit profile')), # str(_('Edit profile')),
str(_('Delete profile')) # str(_('Delete profile'))
] # ]
super().__init__(prompt, profiles, [self._actions[0]], self._actions[1:]) # super().__init__(prompt, profiles, [self._actions[0]], self._actions[1:])
#
def reformat(self, data: List[TProfile]) -> Dict[str, Optional[TProfile]]: # def reformat(self, data: List[TProfile]) -> Dict[str, Optional[TProfile]]:
table = FormattedOutput.as_table(data) # table = FormattedOutput.as_table(data)
rows = table.split('\n') # rows = table.split('\n')
#
# these are the header rows of the table and do not map to any profile obviously # # these are the header rows of the table and do not map to any profile obviously
# we're adding 2 spaces as prefix because the menu selector '> ' will be put before # # we're adding 2 spaces as prefix because the menu selector '> ' will be put before
# the selectable rows so the header has to be aligned # # the selectable rows so the header has to be aligned
display_data: Dict[str, Optional[TProfile]] = {f' {rows[0]}': None, f' {rows[1]}': None} # display_data: Dict[str, Optional[TProfile]] = {f' {rows[0]}': None, f' {rows[1]}': None}
#
for row, profile in zip(rows[2:], data): # for row, profile in zip(rows[2:], data):
row = row.replace('|', '\\|') # row = row.replace('|', '\\|')
display_data[row] = profile # display_data[row] = profile
#
return display_data # return display_data
#
def selected_action_display(self, profile: TProfile) -> str: # def selected_action_display(self, profile: TProfile) -> str:
return profile.name # return profile.name
#
def handle_action( # def handle_action(
self, # self,
action: str, # action: str,
entry: Optional['CustomTypeProfile'], # entry: Optional['CustomTypeProfile'],
data: List['CustomTypeProfile'] # data: List['CustomTypeProfile']
) -> List['CustomTypeProfile']: # ) -> List['CustomTypeProfile']:
if action == self._actions[0]: # add # if action == self._actions[0]: # add
new_profile = self._add_profile() # new_profile = self._add_profile()
if new_profile is not None: # if new_profile is not None:
# in case a profile with the same name as an existing profile # # in case a profile with the same name as an existing profile
# was created we'll replace the existing one # # was created we'll replace the existing one
data = [d for d in data if d.name != new_profile.name] # data = [d for d in data if d.name != new_profile.name]
data += [new_profile] # data += [new_profile]
elif entry is not None: # elif entry is not None:
if action == self._actions[1]: # edit # if action == self._actions[1]: # edit
new_profile = self._add_profile(entry) # new_profile = self._add_profile(entry)
if new_profile is not None: # if new_profile is not None:
# we'll remove the original profile and add the modified version # # we'll remove the original profile and add the modified version
data = [d for d in data if d.name != entry.name and d.name != new_profile.name] # data = [d for d in data if d.name != entry.name and d.name != new_profile.name]
data += [new_profile] # data += [new_profile]
elif action == self._actions[2]: # delete # elif action == self._actions[2]: # delete
data = [d for d in data if d != entry] # data = [d for d in data if d != entry]
#
return data # return data
#
def _is_new_profile_name(self, name: str) -> bool: # def _is_new_profile_name(self, name: str) -> bool:
existing_profile = profile_handler.get_profile_by_name(name) # existing_profile = profile_handler.get_profile_by_name(name)
if existing_profile is not None and existing_profile.profile_type != ProfileType.CustomType: # if existing_profile is not None and existing_profile.profile_type != ProfileType.CustomType:
return False # return False
return True # return True
#
def _add_profile(self, editing: Optional['CustomTypeProfile'] = None) -> Optional['CustomTypeProfile']: # def _add_profile(self, editing: Optional['CustomTypeProfile'] = None) -> Optional['CustomTypeProfile']:
name_prompt = '\n\n' + str(_('Profile name: ')) # name_prompt = '\n\n' + str(_('Profile name: '))
#
while True: # while True:
profile_name = menu.TextInput(name_prompt, editing.name if editing else '').run().strip() # profile_name = menu.TextInput(name_prompt, editing.name if editing else '').run().strip()
#
if not profile_name: # if not profile_name:
return None # return None
#
if not self._is_new_profile_name(profile_name): # if not self._is_new_profile_name(profile_name):
error_prompt = str(_("The profile name you entered is already in use. Try again")) # error_prompt = str(_("The profile name you entered is already in use. Try again"))
print(error_prompt) # print(error_prompt)
else: # else:
break # break
#
packages_prompt = str(_('Packages to be install with this profile (space separated, leave blank to skip): ')) # packages_prompt = str(_('Packages to be install with this profile (space separated, leave blank to skip): '))
edit_packages = ' '.join(editing.packages) if editing else '' # edit_packages = ' '.join(editing.packages) if editing else ''
packages = menu.TextInput(packages_prompt, edit_packages).run().strip() # packages = menu.TextInput(packages_prompt, edit_packages).run().strip()
#
services_prompt = str(_('Services to be enabled with this profile (space separated, leave blank to skip): ')) # services_prompt = str(_('Services to be enabled with this profile (space separated, leave blank to skip): '))
edit_services = ' '.join(editing.services) if editing else '' # edit_services = ' '.join(editing.services) if editing else ''
services = menu.TextInput(services_prompt, edit_services).run().strip() # services = menu.TextInput(services_prompt, edit_services).run().strip()
#
choice = menu.Menu( # choice = menu.Menu(
str(_('Should this profile be enabled for installation?')), # str(_('Should this profile be enabled for installation?')),
menu.Menu.yes_no(), # menu.Menu.yes_no(),
skip=False, # skip=False,
default_option=menu.Menu.no(), # default_option=menu.Menu.no(),
clear_screen=False, # clear_screen=False,
show_search_hint=False # show_search_hint=False
).run() # ).run()
#
enable_profile = True if choice.value == menu.Menu.yes() else False # enable_profile = True if choice.value == menu.Menu.yes() else False
#
profile = CustomTypeProfile( # profile = CustomTypeProfile(
profile_name, # profile_name,
enabled=enable_profile, # enabled=enable_profile,
packages=packages.split(' '), # packages=packages.split(' '),
services=services.split(' ') # services=services.split(' ')
) # )
#
return profile # return profile
#
#
# TODO # # TODO
# Still needs some ironing out # # Still needs some ironing out
class CustomProfile(): # class CustomProfile():
def __init__(self): # def __init__(self):
super().__init__( # super().__init__(
'Custom', # 'Custom',
ProfileType.Custom, # ProfileType.Custom,
description=str(_('Create your own')) # description=str(_('Create your own'))
) # )
#
def json(self) -> Dict[str, Any]: # def json(self) -> Dict[str, Any]:
data: Dict[str, Any] = {'main': self.name, 'gfx_driver': self.gfx_driver, 'custom': []} # data: Dict[str, Any] = {'main': self.name, 'gfx_driver': self.gfx_driver, 'custom': []}
#
for profile in self._current_selection: # for profile in self._current_selection:
data['custom'].append({ # data['custom'].append({
'name': profile.name, # 'name': profile.name,
'packages': profile.packages, # 'packages': profile.packages,
'services': profile.services, # 'services': profile.services,
'enabled': profile.custom_enabled # 'enabled': profile.custom_enabled
}) # })
#
return data # return data
#
def do_on_select(self) -> SelectResult: # def do_on_select(self) -> SelectResult:
custom_profile_list = CustomProfileList('', profile_handler.get_custom_profiles()) # custom_profile_list = CustomProfileList('', profile_handler.get_custom_profiles())
custom_profiles = custom_profile_list.run() # custom_profiles = custom_profile_list.run()
#
# we'll first remove existing custom default_profiles with # # we'll first remove existing custom default_profiles with
# the same name and then add the new ones this # # the same name and then add the new ones this
# will avoid errors of default_profiles with duplicate naming # # will avoid errors of default_profiles with duplicate naming
profile_handler.remove_custom_profiles(custom_profiles) # profile_handler.remove_custom_profiles(custom_profiles)
profile_handler.add_custom_profiles(custom_profiles) # profile_handler.add_custom_profiles(custom_profiles)
#
self.set_current_selection(custom_profiles) # self.set_current_selection(custom_profiles)
#
if custom_profile_list.is_last_choice_cancel(): # if custom_profile_list.is_last_choice_cancel():
return SelectResult.SameSelection # return SelectResult.SameSelection
#
enabled_profiles = [p for p in self._current_selection if p.custom_enabled] # enabled_profiles = [p for p in self._current_selection if p.custom_enabled]
# in case we only created inactive default_profiles we wanna store them but # # in case we only created inactive default_profiles we wanna store them but
# we want to reset the original setting # # we want to reset the original setting
if not enabled_profiles: # if not enabled_profiles:
return SelectResult.ResetCurrent # return SelectResult.ResetCurrent
#
return SelectResult.NewSelection # return SelectResult.NewSelection
#
def post_install(self, install_session: 'Installer'): # def post_install(self, install_session: 'Installer'):
for profile in self._current_selection: # for profile in self._current_selection:
profile.post_install(install_session) # profile.post_install(install_session)
#
def install(self, install_session: 'Installer'): # def install(self, install_session: 'Installer'):
driver_packages = self.gfx_driver_packages() # driver_packages = self.gfx_driver_packages()
install_session.add_additional_packages(driver_packages) # install_session.add_additional_packages(driver_packages)
#
for profile in self._current_selection: # for profile in self._current_selection:
if profile.custom_enabled: # if profile.custom_enabled:
log(f'Installing custom profile {profile.name}...') # log(f'Installing custom profile {profile.name}...')
#
install_session.add_additional_packages(profile.packages) # install_session.add_additional_packages(profile.packages)
install_session.enable_service(profile.services) # install_session.enable_service(profile.services)
#
profile.install(install_session) # profile.install(install_session)
#
def info(self) -> Optional[ProfileInfo]: # def info(self) -> Optional[ProfileInfo]:
enabled_profiles = [p for p in self._current_selection if p.custom_enabled] # enabled_profiles = [p for p in self._current_selection if p.custom_enabled]
if enabled_profiles: # if enabled_profiles:
details = ', '.join([p.name for p in enabled_profiles]) # details = ', '.join([p.name for p in enabled_profiles])
gfx_driver = self.gfx_driver # gfx_driver = self.gfx_driver
return ProfileInfo(self.name, details, gfx_driver) # return ProfileInfo(self.name, details, gfx_driver)
#
return None # return None
#
def reset(self): # def reset(self):
for profile in self._current_selection: # for profile in self._current_selection:
profile.set_enabled(False) # profile.set_enabled(False)
#
self.gfx_driver = None # self.gfx_driver = None
#
#
class CustomTypeProfile(Profile): # class CustomTypeProfile(Profile):
def __init__( # def __init__(
self, # self,
name: str, # name: str,
enabled: bool = False, # enabled: bool = False,
packages: List[str] = [], # packages: List[str] = [],
services: List[str] = [] # services: List[str] = []
): # ):
super().__init__( # super().__init__(
name, # name,
ProfileType.CustomType, # ProfileType.CustomType,
packages=packages, # packages=packages,
services=services, # services=services,
support_gfx_driver=True # support_gfx_driver=True
) # )
#
self.custom_enabled = enabled # self.custom_enabled = enabled
#
def json(self) -> Dict[str, Any]: # def json(self) -> Dict[str, Any]:
return { # return {
'name': self.name, # 'name': self.name,
'packages': self.packages, # 'packages': self.packages,
'services': self.services, # 'services': self.services,
'enabled': self.custom_enabled # 'enabled': self.custom_enabled
} # }

View File

@ -71,28 +71,28 @@ class ProfileHandler:
else: else:
self._import_profile_from_url(url_path) self._import_profile_from_url(url_path)
if custom := profile_config.get('custom', None): # if custom := profile_config.get('custom', None):
from archinstall.default_profiles.custom import CustomTypeProfile # from archinstall.default_profiles.custom import CustomTypeProfile
custom_types = [] # custom_types = []
#
for entry in custom: # for entry in custom:
custom_types.append( # custom_types.append(
CustomTypeProfile( # CustomTypeProfile(
entry['name'], # entry['name'],
entry['enabled'], # entry['enabled'],
entry.get('packages', []), # entry.get('packages', []),
entry.get('services', []) # entry.get('services', [])
) # )
) # )
#
self.remove_custom_profiles(custom_types) # self.remove_custom_profiles(custom_types)
self.add_custom_profiles(custom_types) # self.add_custom_profiles(custom_types)
#
# this doesn't mean it's actual going to be set as a selection # # this doesn't mean it's actual going to be set as a selection
# but we are simply populating the custom profile with all # # but we are simply populating the custom profile with all
# possible custom definitions # # possible custom definitions
if custom_profile := self.get_profile_by_name('Custom'): # if custom_profile := self.get_profile_by_name('Custom'):
custom_profile.set_current_selection(custom_types) # custom_profile.set_current_selection(custom_types)
if main := profile_config.get('main', None): if main := profile_config.get('main', None):
profile = self.get_profile_by_name(main) if main else None profile = self.get_profile_by_name(main) if main else None

View File

@ -10,6 +10,5 @@ exclude = (?x)(^archinstall/lib/disk/btrfs/btrfssubvolumeinfo\.py$
| ^archinstall/lib/installer\.py$ | ^archinstall/lib/installer\.py$
| ^archinstall/lib/systemd\.py$ | ^archinstall/lib/systemd\.py$
| ^archinstall/lib/user_interaction/general_conf\.py$ | ^archinstall/lib/user_interaction/general_conf\.py$
| ^archinstall/lib/user_interaction/locale_conf\.py$ | ^archinstall/lib/user_interaction/locale_conf\.py$)
| ^archinstall/default_profiles/custom\.py$)
files = archinstall/ files = archinstall/