More formatting fixes

This commit is contained in:
Dylan Taylor 2021-05-15 12:59:38 -04:00
parent e966bef891
commit 6057203e5b
11 changed files with 121 additions and 97 deletions

View File

@ -1,57 +1,79 @@
# Contributing to archinstall # Contributing to archinstall
Any contributions through pull requests are welcome as this project aims to be a community based project to ease some Arch Linux installation steps. Bear in mind that in the future this repo might be transferred to the official [GitLab repo under Arch Linux](http://gitlab.archlinux.org/archlinux/) *(if GitLab becomes open to the general public)*. Any contributions through pull requests are welcome as this project aims to be a community based project to ease some
Arch Linux installation steps. Bear in mind that in the future this repo might be transferred to the
official [GitLab repo under Arch Linux](http://gitlab.archlinux.org/archlinux/) *(if GitLab becomes open to the general
public)*.
Therefore guidelines and style changes to the code might come into affect as well as guidelines surrounding bug reporting and discussions. Therefore guidelines and style changes to the code might come into affect as well as guidelines surrounding bug
reporting and discussions.
## Branches ## Branches
`master` is currently the default branch, and that's where all future feature work is being done, this means that `master` is a living entity and will most likely never be in a fully stable state. For stable releases, please see the tagged commits. `master` is currently the default branch, and that's where all future feature work is being done, this means
that `master` is a living entity and will most likely never be in a fully stable state. For stable releases, please see
the tagged commits.
Patch releases will be done against their own branches, branched from stable tagged releases and will be named according to the version it will become on release *(Patches to `v2.1.4` will be done on branch `v2.1.5` for instance)*. Patch releases will be done against their own branches, branched from stable tagged releases and will be named according
to the version it will become on release *(Patches to `v2.1.4` will be done on branch `v2.1.5` for instance)*.
## Discussions ## Discussions
Currently, questions, bugs and suggestions should be reported through [GitHub issue tracker](https://github.com/archlinux/archinstall/issues).<br> Currently, questions, bugs and suggestions should be reported
through [GitHub issue tracker](https://github.com/archlinux/archinstall/issues).<br>
For less formal discussions there are also a [archinstall Discord server](https://discord.gg/cqXU88y). For less formal discussions there are also a [archinstall Discord server](https://discord.gg/cqXU88y).
## Coding convention ## Coding convention
Archinstall's goal is to follow [PEP8](https://www.python.org/dev/peps/pep-0008/) as best as it can with some minor exceptions.<br> Archinstall's goal is to follow [PEP8](https://www.python.org/dev/peps/pep-0008/) as best as it can with some minor
exceptions.<br>
The exceptions to PEP8 are: The exceptions to PEP8 are:
* Archinstall uses [tabs instead of spaces](https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces) simply to make it easier for non-IDE developers to navigate the code *(Tab display-width should be equal to 4 spaces)*. Exception to the rule are comments that need fine-tuned indentation for documentation purposes. * Archinstall uses [tabs instead of spaces](https://www.python.org/dev/peps/pep-0008/#tabs-or-spaces) simply to make it
* [Line length](https://www.python.org/dev/peps/pep-0008/#maximum-line-length) should aim for no more than 100 characters, but not strictly enforced. easier for non-IDE developers to navigate the code *(Tab display-width should be equal to 4 spaces)*. Exception to the
* [Line breaks before/after binary operator](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator) is not enforced, as long as the style of line breaks are consistent within the same code block. rule are comments that need fine-tuned indentation for documentation purposes.
* Archinstall should always be saved with **Unix-formatted line endings** and no other platform-specific formats. * [Line length](https://www.python.org/dev/peps/pep-0008/#maximum-line-length) should aim for no more than 100
* [Blank lines](https://www.python.org/dev/peps/pep-0008/#blank-lines) before/after imports and functions are not followed and discouraged. One space is commonly used in archinstall. characters, but not strictly enforced.
* Multiple [Imports](https://www.python.org/dev/peps/pep-0008/#imports) on the same line is allowed, but more than five imports should be avoided on any given line. This simply saves up some space at the top of the file *(for non-IDE developers)* and will not be enforced. * [Line breaks before/after binary operator](https://www.python.org/dev/peps/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
* [String quotes](https://www.python.org/dev/peps/pep-0008/#string-quotes) follow PEP8, the exception being when creating formatted strings, double-quoted strings are *preferred* but not required on the outer edges *(Example: `f"Welcome {name}"` rather than `f'Welcome {name}'`)*. is not enforced, as long as the style of line breaks are consistent within the same code block.
* Archinstall should always be saved with **Unix-formatted line endings** and no other platform-specific formats.
* [Blank lines](https://www.python.org/dev/peps/pep-0008/#blank-lines) before/after imports and functions are not
followed and discouraged. One space is commonly used in archinstall.
* Multiple [Imports](https://www.python.org/dev/peps/pep-0008/#imports) on the same line is allowed, but more than five
imports should be avoided on any given line. This simply saves up some space at the top of the file *(for non-IDE
developers)* and will not be enforced.
* [String quotes](https://www.python.org/dev/peps/pep-0008/#string-quotes) follow PEP8, the exception being when
creating formatted strings, double-quoted strings are *preferred* but not required on the outer edges *(
Example: `f"Welcome {name}"` rather than `f'Welcome {name}'`)*.
Most of these style guidelines have been put into place after the fact *(in an attempt to clean up the code)*.<br> Most of these style guidelines have been put into place after the fact *(in an attempt to clean up the code)*.<br>
There might therefore be older code which does not follow the coding convention and the code is subject to change. There might therefore be older code which does not follow the coding convention and the code is subject to change.
## Submitting Changes ## Submitting Changes
Archinstall uses Github's pull-request workflow and all contributions in terms of code should be done through pull requests.<br> Archinstall uses Github's pull-request workflow and all contributions in terms of code should be done through pull
requests.<br>
Anyone interested in archinstall may review your code. One of the core developers will merge your pull request when they think it is ready. Anyone interested in archinstall may review your code. One of the core developers will merge your pull request when they
For every pull request, we aim to promptly either merge it or say why it is not yet ready; if you go a few days without a reply, please feel free to ping the thread by adding a new comment. think it is ready. For every pull request, we aim to promptly either merge it or say why it is not yet ready; if you go
a few days without a reply, please feel free to ping the thread by adding a new comment.
To get your pull request merged sooner, you should explain why you are making the change. For example, you can point to a code sample that is outdated in terms of Arch Linux command lines. To get your pull request merged sooner, you should explain why you are making the change. For example, you can point to
It is also helpful to add links to online documentation or to the implementation of the code you are changing. a code sample that is outdated in terms of Arch Linux command lines. It is also helpful to add links to online
documentation or to the implementation of the code you are changing.
Also, do not squash your commits after you have submitted a pull request, as this erases context during review. We will squash commits when the pull request is merged. Also, do not squash your commits after you have submitted a pull request, as this erases context during review. We will
squash commits when the pull request is merged.
At present the current contributors are (alphabetically): At present the current contributors are (alphabetically):
* Anton Hvornum ([@Torxed](https://github.com/Torxed)) * Anton Hvornum ([@Torxed](https://github.com/Torxed))
* Borislav Kosharov ([@nikibobi](https://github.com/nikibobi)) * Borislav Kosharov ([@nikibobi](https://github.com/nikibobi))
* demostanis ([@demostanis](https://github.com/demostanis)) * demostanis ([@demostanis](https://github.com/demostanis))
* Giancarlo Razzolini (@[grazzolini](https://github.com/grazzolini)) * Giancarlo Razzolini (@[grazzolini](https://github.com/grazzolini))
* j-james ([@j-james](https://github.com/j-james)) * j-james ([@j-james](https://github.com/j-james))
* Jerker Bengtsson ([@jaybent](https://github.com/jaybent)) * Jerker Bengtsson ([@jaybent](https://github.com/jaybent))
* Ninchester ([@ninchester](https://github.com/ninchester)) * Ninchester ([@ninchester](https://github.com/ninchester))
* Philipp Schaffrath ([@phisch](https://github.com/phisch)) * Philipp Schaffrath ([@phisch](https://github.com/phisch))
* Varun Madiath ([@vamega](https://github.com/vamega)) * Varun Madiath ([@vamega](https://github.com/vamega))
* nullrequest ([@advaithm](https://github.com/advaithm)) * nullrequest ([@advaithm](https://github.com/advaithm))

View File

@ -60,7 +60,7 @@ def insert_mirrors(mirrors, *args, **kwargs):
return True return True
def use_mirrors(regions :dict, destination='/etc/pacman.d/mirrorlist'): def use_mirrors(regions: dict, destination='/etc/pacman.d/mirrorlist'):
log(f'A new package mirror-list has been created: {destination}', level=logging.INFO) log(f'A new package mirror-list has been created: {destination}', level=logging.INFO)
for region, mirrors in regions.items(): for region, mirrors in regions.items():
with open(destination, 'w') as mirrorlist: with open(destination, 'w') as mirrorlist:
@ -86,7 +86,6 @@ def list_mirrors():
log(f'Could not fetch an active mirror-list: {err}', level=logging.WARNING, fg="yellow") log(f'Could not fetch an active mirror-list: {err}', level=logging.WARNING, fg="yellow")
return regions return regions
region = 'Unknown region' region = 'Unknown region'
for line in response.readlines(): for line in response.readlines():
if len(line.strip()) == 0: if len(line.strip()) == 0:

View File

@ -1,8 +1,9 @@
import os
import fcntl import fcntl
import os
import socket import socket
import struct import struct
from collections import OrderedDict from collections import OrderedDict
from .exceptions import * from .exceptions import *
from .general import sys_command from .general import sys_command
from .storage import storage from .storage import storage
@ -10,7 +11,7 @@ from .storage import storage
def get_hw_addr(ifname): def get_hw_addr(ifname):
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', bytes(ifname, 'utf-8')[:15])) info = fcntl.ioctl(s.fileno(), 0x8927, struct.pack('256s', bytes(ifname, 'utf-8')[:15]))
return ':'.join('%02x' % b for b in info[18:24]) return ':'.join('%02x' % b for b in info[18:24])
@ -25,7 +26,7 @@ def list_interfaces(skip_loopback=True):
return interfaces return interfaces
def enrich_iface_types(interfaces :dict): def enrich_iface_types(interfaces: dict):
result = {} result = {}
for iface in interfaces: for iface in interfaces:
if os.path.isdir(f"/sys/class/net/{iface}/bridge/"): if os.path.isdir(f"/sys/class/net/{iface}/bridge/"):

View File

@ -1,8 +1,9 @@
import abc import abc
import logging
import os import os
import sys import sys
import logging
from pathlib import Path from pathlib import Path
from .storage import storage from .storage import storage
@ -21,7 +22,7 @@ class journald(dict):
@abc.abstractmethod @abc.abstractmethod
def log(message, level=logging.DEBUG): def log(message, level=logging.DEBUG):
try: try:
import systemd.journal # type: ignore import systemd.journal # type: ignore
except ModuleNotFoundError: except ModuleNotFoundError:
return False return False
@ -77,8 +78,8 @@ def supports_color():
# Heavily influenced by: https://github.com/django/django/blob/ae8338daf34fd746771e0678081999b656177bae/django/utils/termcolors.py#L13 # Heavily influenced by: https://github.com/django/django/blob/ae8338daf34fd746771e0678081999b656177bae/django/utils/termcolors.py#L13
# Color options here: https://askubuntu.com/questions/528928/how-to-do-underline-bold-italic-strikethrough-color-background-and-size-i # Color options here: https://askubuntu.com/questions/528928/how-to-do-underline-bold-italic-strikethrough-color-background-and-size-i
def stylize_output(text :str, *opts, **kwargs): def stylize_output(text: str, *opts, **kwargs):
opt_dict = {'bold': '1', 'italic' : '3', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'} opt_dict = {'bold': '1', 'italic': '3', 'underscore': '4', 'blink': '5', 'reverse': '7', 'conceal': '8'}
color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white') color_names = ('black', 'red', 'green', 'yellow', 'blue', 'magenta', 'cyan', 'white')
foreground = {color_names[x]: '3%s' % x for x in range(8)} foreground = {color_names[x]: '3%s' % x for x in range(8)}
background = {color_names[x]: '4%s' % x for x in range(8)} background = {color_names[x]: '4%s' % x for x in range(8)}
@ -120,8 +121,8 @@ def log(*args, **kwargs):
log_file.write("") log_file.write("")
except PermissionError: except PermissionError:
# Fallback to creating the log file in the current folder # Fallback to creating the log file in the current folder
err_string = f"Not enough permission to place log file at {absolute_logfile}, creating it in {Path('./').absolute()/filename} instead." err_string = f"Not enough permission to place log file at {absolute_logfile}, creating it in {Path('./').absolute() / filename} instead."
absolute_logfile = Path('./').absolute()/filename absolute_logfile = Path('./').absolute() / filename
absolute_logfile.parents[0].mkdir(exist_ok=True) absolute_logfile.parents[0].mkdir(exist_ok=True)
absolute_logfile = str(absolute_logfile) absolute_logfile = str(absolute_logfile)
storage['LOG_PATH'] = './' storage['LOG_PATH'] = './'

View File

@ -51,7 +51,7 @@ def find_packages(*names):
return result return result
def validate_package_list(packages :list): def validate_package_list(packages: list):
""" """
Validates a list of given packages. Validates a list of given packages.
Raises `RequirementError` if one or more packages are not found. Raises `RequirementError` if one or more packages are not found.

View File

@ -7,6 +7,7 @@ import sys
import urllib.parse import urllib.parse
import urllib.request import urllib.request
from typing import Optional from typing import Optional
from .general import multisplit from .general import multisplit
from .networking import * from .networking import *
from .storage import storage from .storage import storage
@ -16,7 +17,7 @@ def grab_url_data(path):
safe_path = path[:path.find(':')+1]+''.join([item if item in ('/', '?', '=', '&') else urllib.parse.quote(item) for item in multisplit(path[path.find(':')+1:], ('/', '?', '=', '&'))]) safe_path = path[:path.find(':')+1]+''.join([item if item in ('/', '?', '=', '&') else urllib.parse.quote(item) for item in multisplit(path[path.find(':')+1:], ('/', '?', '=', '&'))])
ssl_context = ssl.create_default_context() ssl_context = ssl.create_default_context()
ssl_context.check_hostname = False ssl_context.check_hostname = False
ssl_context.verify_mode=ssl.CERT_NONE ssl_context.verify_mode = ssl.CERT_NONE
response = urllib.request.urlopen(safe_path, context=ssl_context) response = urllib.request.urlopen(safe_path, context=ssl_context)
return response.read() return response.read()
@ -29,7 +30,7 @@ def list_profiles(filter_irrelevant_macs=True, subpath='', filter_top_level_prof
cache = {} cache = {}
# Grab all local profiles found in PROFILE_PATH # Grab all local profiles found in PROFILE_PATH
for PATH_ITEM in storage['PROFILE_PATH']: for PATH_ITEM in storage['PROFILE_PATH']:
for root, folders, files in os.walk(os.path.abspath(os.path.expanduser(PATH_ITEM+subpath))): for root, folders, files in os.walk(os.path.abspath(os.path.expanduser(PATH_ITEM + subpath))):
for file in files: for file in files:
if file == '__init__.py': if file == '__init__.py':
continue continue
@ -51,7 +52,7 @@ def list_profiles(filter_irrelevant_macs=True, subpath='', filter_top_level_prof
# Grab profiles from upstream URL # Grab profiles from upstream URL
if storage['PROFILE_DB']: if storage['PROFILE_DB']:
profiles_url = os.path.join(storage["UPSTREAM_URL"]+subpath, storage['PROFILE_DB']) profiles_url = os.path.join(storage["UPSTREAM_URL"] + subpath, storage['PROFILE_DB'])
try: try:
profile_list = json.loads(grab_url_data(profiles_url)) profile_list = json.loads(grab_url_data(profiles_url))
except urllib.error.HTTPError as err: except urllib.error.HTTPError as err:
@ -74,7 +75,7 @@ def list_profiles(filter_irrelevant_macs=True, subpath='', filter_top_level_prof
if filter_top_level_profiles: if filter_top_level_profiles:
for profile in list(cache.keys()): for profile in list(cache.keys()):
if Profile(None, profile).is_top_level_profile() is False: if Profile(None, profile).is_top_level_profile() is False:
del(cache[profile]) del (cache[profile])
return cache return cache
@ -166,7 +167,7 @@ class Profile(Script):
super(Profile, self).__init__(path, installer) super(Profile, self).__init__(path, installer)
def __dump__(self, *args, **kwargs): def __dump__(self, *args, **kwargs):
return {'path' : self.path} return {'path': self.path}
def __repr__(self, *args, **kwargs): def __repr__(self, *args, **kwargs):
return f'Profile({os.path.basename(self.profile)})' return f'Profile({os.path.basename(self.profile)})'

View File

@ -8,15 +8,15 @@ import os
# #
# And Keeping this in dict ensures that variables are shared across imports. # And Keeping this in dict ensures that variables are shared across imports.
storage = { storage = {
'PROFILE_PATH' : [ 'PROFILE_PATH': [
'./profiles', './profiles',
'~/.config/archinstall/profiles', '~/.config/archinstall/profiles',
os.path.join(os.path.dirname(os.path.abspath(__file__)), 'profiles'), os.path.join(os.path.dirname(os.path.abspath(__file__)), 'profiles'),
# os.path.abspath(f'{os.path.dirname(__file__)}/../examples') # os.path.abspath(f'{os.path.dirname(__file__)}/../examples')
], ],
'UPSTREAM_URL' : 'https://raw.githubusercontent.com/archlinux/archinstall/master/profiles', 'UPSTREAM_URL': 'https://raw.githubusercontent.com/archlinux/archinstall/master/profiles',
'PROFILE_DB' : None, # Used in cases when listing profiles is desired, not mandatory for direct profile grabing. 'PROFILE_DB': None, # Used in cases when listing profiles is desired, not mandatory for direct profile grabing.
'LOG_PATH' : '/var/log/archinstall', 'LOG_PATH': '/var/log/archinstall',
'LOG_FILE' : 'install.log', 'LOG_FILE': 'install.log',
'MOUNT_POINT' : '/mnt' 'MOUNT_POINT': '/mnt'
} }

View File

@ -48,6 +48,7 @@ def check_for_correct_username(username):
def do_countdown(): def do_countdown():
SIG_TRIGGER = False SIG_TRIGGER = False
def kill_handler(sig, frame): def kill_handler(sig, frame):
print() print()
exit(0) exit(0)
@ -101,17 +102,17 @@ def print_large_list(options, padding=5, margin_bottom=0, separator=': '):
longest_line = highest_index_number_length + len(separator) + get_longest_option(options) + padding longest_line = highest_index_number_length + len(separator) + get_longest_option(options) + padding
spaces_without_option = longest_line - (len(separator) + highest_index_number_length) spaces_without_option = longest_line - (len(separator) + highest_index_number_length)
max_num_of_columns = get_terminal_width() // longest_line max_num_of_columns = get_terminal_width() // longest_line
max_options_in_cells = max_num_of_columns * (get_terminal_height()-margin_bottom) max_options_in_cells = max_num_of_columns * (get_terminal_height() - margin_bottom)
if (len(options) > max_options_in_cells): if (len(options) > max_options_in_cells):
for index, option in enumerate(options): for index, option in enumerate(options):
print(f"{index}: {option}") print(f"{index}: {option}")
return 1, index return 1, index
else: else:
for row in range(0, (get_terminal_height()-margin_bottom)): for row in range(0, (get_terminal_height() - margin_bottom)):
for column in range(row, len(options), (get_terminal_height()-margin_bottom)): for column in range(row, len(options), (get_terminal_height() - margin_bottom)):
spaces = " "*(spaces_without_option - len(options[column])) spaces = " " * (spaces_without_option - len(options[column]))
print(f"{str(column): >{highest_index_number_length}}{separator}{options[column]}", end = spaces) print(f"{str(column): >{highest_index_number_length}}{separator}{options[column]}", end=spaces)
print() print()
return column, row return column, row
@ -148,7 +149,7 @@ def generic_multi_select(options, text="Select one or more of the options above
else: else:
printed_options.append(f'{option}') printed_options.append(f'{option}')
section.clear(0, get_terminal_height()-section._cursor_y-1) section.clear(0, get_terminal_height() - section._cursor_y - 1)
print_large_list(printed_options, margin_bottom=2) print_large_list(printed_options, margin_bottom=2)
section._cursor_y = len(printed_options) section._cursor_y = len(printed_options)
section._cursor_x = 0 section._cursor_x = 0
@ -204,7 +205,7 @@ class MiniCurses:
sys.stdout.flush() sys.stdout.flush()
sys.stdout.write("\033[%dG" % 0) sys.stdout.write("\033[%dG" % 0)
sys.stdout.flush() sys.stdout.flush()
sys.stdout.write(" " * (get_terminal_width()-1)) sys.stdout.write(" " * (get_terminal_width() - 1))
sys.stdout.flush() sys.stdout.flush()
sys.stdout.write("\033[%dG" % 0) sys.stdout.write("\033[%dG" % 0)
sys.stdout.flush() sys.stdout.flush()
@ -223,17 +224,17 @@ class MiniCurses:
sys.stdout.flush() sys.stdout.flush()
sys.stdout.write('\033[%d;%df' % (y, x)) sys.stdout.write('\033[%d;%df' % (y, x))
for line in range(get_terminal_height()-y-1, y): for line in range(get_terminal_height() - y - 1, y):
sys.stdout.write(" " * (get_terminal_width()-1)) sys.stdout.write(" " * (get_terminal_width() - 1))
sys.stdout.flush() sys.stdout.flush()
sys.stdout.write('\033[%d;%df' % (y, x)) sys.stdout.write('\033[%d;%df' % (y, x))
sys.stdout.flush() sys.stdout.flush()
def deal_with_control_characters(self, char): def deal_with_control_characters(self, char):
mapper = { mapper = {
'\x7f' : 'BACKSPACE', '\x7f': 'BACKSPACE',
'\r' : 'CR', '\r': 'CR',
'\n' : 'NL' '\n': 'NL'
} }
if (mapped_char := mapper.get(char, None)) == 'BACKSPACE': if (mapped_char := mapper.get(char, None)) == 'BACKSPACE':
@ -319,7 +320,7 @@ def ask_for_superuser_account(prompt='Username for required superuser with sudo
continue continue
password = get_password(prompt=f'Password for user {new_user}: ') password = get_password(prompt=f'Password for user {new_user}: ')
return {new_user: {"!password" : password}} return {new_user: {"!password": password}}
def ask_for_additional_users(prompt='Any additional users to install (leave blank for no users): '): def ask_for_additional_users(prompt='Any additional users to install (leave blank for no users): '):
@ -335,9 +336,9 @@ def ask_for_additional_users(prompt='Any additional users to install (leave blan
password = get_password(prompt=f'Password for user {new_user}: ') password = get_password(prompt=f'Password for user {new_user}: ')
if input("Should this user be a superuser (sudoer) [y/N]: ").strip(' ').lower() in ('y', 'yes'): if input("Should this user be a superuser (sudoer) [y/N]: ").strip(' ').lower() in ('y', 'yes'):
superusers[new_user] = {"!password" : password} superusers[new_user] = {"!password": password}
else: else:
users[new_user] = {"!password" : password} users[new_user] = {"!password": password}
return users, superusers return users, superusers
@ -347,7 +348,7 @@ def ask_for_a_timezone():
timezone = input('Enter a valid timezone (examples: Europe/Stockholm, US/Eastern) or press enter to use UTC: ').strip().strip('*.') timezone = input('Enter a valid timezone (examples: Europe/Stockholm, US/Eastern) or press enter to use UTC: ').strip().strip('*.')
if timezone == '': if timezone == '':
timezone = 'UTC' timezone = 'UTC'
if (pathlib.Path("/usr")/"share"/"zoneinfo"/timezone).exists(): if (pathlib.Path("/usr") / "share" / "zoneinfo" / timezone).exists():
return timezone return timezone
else: else:
log( log(
@ -359,17 +360,17 @@ def ask_for_a_timezone():
def ask_for_bootloader() -> str: def ask_for_bootloader() -> str:
bootloader = "systemd-bootctl" bootloader = "systemd-bootctl"
if hasUEFI()==False: if hasUEFI() == False:
bootloader="grub-install" bootloader = "grub-install"
else: else:
bootloader_choice = input("Would you like to use GRUB as a bootloader instead of systemd-boot? [y/N] ").lower() bootloader_choice = input("Would you like to use GRUB as a bootloader instead of systemd-boot? [y/N] ").lower()
if bootloader_choice == "y": if bootloader_choice == "y":
bootloader="grub-install" bootloader = "grub-install"
return bootloader return bootloader
def ask_for_audio_selection(): def ask_for_audio_selection():
audio = "pulseaudio" # Default for most desktop environments audio = "pulseaudio" # Default for most desktop environments
pipewire_choice = input("Would you like to install pipewire instead of pulseaudio as the default audio server? [Y/n] ").lower() pipewire_choice = input("Would you like to install pipewire instead of pulseaudio as the default audio server? [Y/n] ").lower()
if pipewire_choice in ("y", ""): if pipewire_choice in ("y", ""):
audio = "pipewire" audio = "pipewire"
@ -379,18 +380,18 @@ def ask_for_audio_selection():
def ask_to_configure_network(): def ask_to_configure_network():
# Optionally configure one network interface. # Optionally configure one network interface.
#while 1: # while 1:
# {MAC: Ifname} # {MAC: Ifname}
interfaces = { interfaces = {
'ISO-CONFIG' : 'Copy ISO network configuration to installation', 'ISO-CONFIG': 'Copy ISO network configuration to installation',
'NetworkManager':'Use NetworkManager to control and manage your internet connection', 'NetworkManager': 'Use NetworkManager to control and manage your internet connection',
**list_interfaces() **list_interfaces()
} }
nic = generic_select(interfaces, "Select one network interface to configure (leave blank to skip): ") nic = generic_select(interfaces, "Select one network interface to configure (leave blank to skip): ")
if nic and nic != 'Copy ISO network configuration to installation': if nic and nic != 'Copy ISO network configuration to installation':
if nic == 'Use NetworkManager to control and manage your internet connection': if nic == 'Use NetworkManager to control and manage your internet connection':
return {'nic': nic,'NetworkManager':True} return {'nic': nic, 'NetworkManager': True}
# Current workaround: # Current workaround:
# For selecting modes without entering text within brackets, # For selecting modes without entering text within brackets,
@ -401,7 +402,7 @@ def ask_to_configure_network():
print(f"{index}: {mode}") print(f"{index}: {mode}")
mode = generic_select(['DHCP', 'IP'], f"Select which mode to configure for {nic} or leave blank for DHCP: ", mode = generic_select(['DHCP', 'IP'], f"Select which mode to configure for {nic} or leave blank for DHCP: ",
options_output=False) options_output=False)
if mode == 'IP': if mode == 'IP':
while 1: while 1:
ip = input(f"Enter the IP and subnet for {nic} (example: 192.168.0.5/24): ").strip() ip = input(f"Enter the IP and subnet for {nic} (example: 192.168.0.5/24): ").strip()
@ -436,7 +437,7 @@ def ask_to_configure_network():
if len(dns_input := input('Enter your DNS servers (space separated, blank for none): ').strip()): if len(dns_input := input('Enter your DNS servers (space separated, blank for none): ').strip()):
dns = dns_input.split(' ') dns = dns_input.split(' ')
return {'nic': nic, 'dhcp': False, 'ip': ip, 'gateway' : gateway, 'dns' : dns} return {'nic': nic, 'dhcp': False, 'ip': ip, 'gateway': gateway, 'dns': dns}
else: else:
return {'nic': nic} return {'nic': nic}
elif nic: elif nic:
@ -447,26 +448,26 @@ def ask_to_configure_network():
def ask_for_disk_layout(): def ask_for_disk_layout():
options = { options = {
'keep-existing' : 'Keep existing partition layout and select which ones to use where', 'keep-existing': 'Keep existing partition layout and select which ones to use where',
'format-all' : 'Format entire drive and setup a basic partition scheme', 'format-all': 'Format entire drive and setup a basic partition scheme',
'abort' : 'Abort the installation' 'abort': 'Abort the installation'
} }
value = generic_select(options, "Found partitions on the selected drive, (select by number) what you want to do: ", value = generic_select(options, "Found partitions on the selected drive, (select by number) what you want to do: ",
allow_empty_input=False, sort=True) allow_empty_input=False, sort=True)
return next((key for key, val in options.items() if val == value), None) return next((key for key, val in options.items() if val == value), None)
def ask_for_main_filesystem_format(): def ask_for_main_filesystem_format():
options = { options = {
'btrfs' : 'btrfs', 'btrfs': 'btrfs',
'ext4' : 'ext4', 'ext4': 'ext4',
'xfs' : 'xfs', 'xfs': 'xfs',
'f2fs' : 'f2fs' 'f2fs': 'f2fs'
} }
value = generic_select(options, "Select which filesystem your main partition should use (by number or name): ", value = generic_select(options, "Select which filesystem your main partition should use (by number or name): ",
allow_empty_input=False) allow_empty_input=False)
return next((key for key, val in options.items() if val == value), None) return next((key for key, val in options.items() if val == value), None)
@ -526,7 +527,7 @@ def generic_select(options, input_text="Select one of the above by index or abso
selected_option = options[selected_option] selected_option = options[selected_option]
break break
elif selected_option in options: elif selected_option in options:
break # We gave a correct absolute value break # We gave a correct absolute value
else: else:
raise RequirementError(f'Selected option "{selected_option}" does not exist in available options') raise RequirementError(f'Selected option "{selected_option}" does not exist in available options')
except RequirementError as err: except RequirementError as err:
@ -584,7 +585,7 @@ def select_profile(options):
print(' -- (Leave blank and hit enter to skip this step and continue) --') print(' -- (Leave blank and hit enter to skip this step and continue) --')
selected_profile = generic_select(profiles, 'Enter a pre-programmed profile name if you want to install one: ', selected_profile = generic_select(profiles, 'Enter a pre-programmed profile name if you want to install one: ',
options_output=False) options_output=False)
if selected_profile: if selected_profile:
return Profile(None, selected_profile) return Profile(None, selected_profile)
else: else:
@ -674,8 +675,9 @@ def select_mirror_regions(mirrors, show_top_mirrors=True):
print_large_list(regions, margin_bottom=4) print_large_list(regions, margin_bottom=4)
print(' -- You can skip this step by leaving the option blank --') print(' -- You can skip this step by leaving the option blank --')
selected_mirror = generic_select(regions, 'Select one of the above regions to download packages from (by number or full name): ', selected_mirror = generic_select(regions,
options_output=False) 'Select one of the above regions to download packages from (by number or full name): ',
options_output=False)
if not selected_mirror: if not selected_mirror:
# Returning back empty options which can be both used to # Returning back empty options which can be both used to
# do "if x:" logic as well as do `x.get('mirror', {}).get('sub', None)` chaining # do "if x:" logic as well as do `x.get('mirror', {}).get('sub', None)` chaining

View File

@ -43,7 +43,6 @@ author = 'Anton Hvornum'
# The full version, including alpha/beta/rc tags # The full version, including alpha/beta/rc tags
release = 'v2.1.0' release = 'v2.1.0'
# -- General configuration --------------------------------------------------- # -- General configuration ---------------------------------------------------
master_doc = 'index' master_doc = 'index'
@ -64,7 +63,6 @@ templates_path = ['_templates']
# This pattern also affects html_static_path and html_extra_path. # This pattern also affects html_static_path and html_extra_path.
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
# -- Options for HTML output ------------------------------------------------- # -- Options for HTML output -------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for # The theme to use for HTML and HTML Help pages. See the documentation for

View File

@ -12,5 +12,5 @@ If the PR is larger than ~20 lines, please describe it here unless described in
# Testing # Testing
Any new feature or stability improvement should be tested if possible. Any new feature or stability improvement should be tested if possible. Please follow the test instructions at the bottom
Please follow the test instructions at the bottom of the README or use the ISO built on each PR. of the README or use the ISO built on each PR.

View File

@ -1,9 +1,9 @@
import time
import json import json
import logging import logging
import time
import archinstall import archinstall
from archinstall.lib.hardware import hasUEFI from archinstall.lib.hardware import hasUEFI
from archinstall.lib.profiles import Profile
if archinstall.arguments.get('help'): if archinstall.arguments.get('help'):
print("See `man archinstall` for help.") print("See `man archinstall` for help.")