diff --git a/archinstall/lib/configuration.py b/archinstall/lib/configuration.py index c40ef161..12f1cb1c 100644 --- a/archinstall/lib/configuration.py +++ b/archinstall/lib/configuration.py @@ -11,8 +11,9 @@ from archinstall.lib.crypt import encrypt from archinstall.lib.menu.helpers import Confirmation, Selection from archinstall.lib.menu.util import get_password, prompt_dir from archinstall.lib.models.network import NetworkConfiguration -from archinstall.lib.output import as_key_value_pair, debug, logger, warn +from archinstall.lib.output import debug, logger, warn from archinstall.lib.translationhandler import tr +from archinstall.lib.utils.format import as_key_value_pair from archinstall.tui.menu_item import MenuItem, MenuItemGroup from archinstall.tui.result import ResultType diff --git a/archinstall/lib/output.py b/archinstall/lib/output.py index bc9bc7a3..de71228c 100644 --- a/archinstall/lib/output.py +++ b/archinstall/lib/output.py @@ -5,13 +5,12 @@ import urllib.error import urllib.request from collections.abc import Callable from dataclasses import asdict, is_dataclass -from datetime import UTC, datetime from enum import Enum from pathlib import Path from typing import TYPE_CHECKING, Any from archinstall.lib.utils.encoding import unicode_ljust, unicode_rjust -from archinstall.tui.rich import BaseRichTable +from archinstall.lib.utils.util import timestamp if TYPE_CHECKING: from _typeshed import DataclassInstance @@ -112,74 +111,13 @@ class FormattedOutput: return output - @staticmethod - def as_columns(entries: list[str], cols: int) -> str: - """ - Will format a list into a given number of columns - """ - chunks = [] - output = '' - - for i in range(0, len(entries), cols): - chunks.append(entries[i : i + cols]) - - for row in chunks: - out_fmt = '{: <30} ' * len(row) - output += out_fmt.format(*row) + '\n' - - return output - - -def as_key_value_pair( - entries: dict[str, str | list[str] | bool], - ignore_empty: bool = True, -) -> str: - """ - Formats key-values as a Rich Table: - key1 : value1 - key2 : value2 - ... - """ - table = BaseRichTable() - table.add_column('key', style='bold', no_wrap=True) - table.add_column('value', style='white', max_width=70) - - for label, value in entries.items(): - if ignore_empty and not value: - continue - - if isinstance(value, bool): - value = 'Yes' if value else 'No' - - if isinstance(value, list): - value = '\n '.join(str(val) for val in value) - - table.add_row(label.title(), f': {value}') - - return table.stringify() - - -class Journald: - @staticmethod - def log(message: str, level: int = logging.DEBUG) -> None: - try: - import systemd.journal # type: ignore[import-not-found] - except ModuleNotFoundError: - return - - log_adapter = logging.getLogger('archinstall') - log_fmt = logging.Formatter('[%(levelname)s]: %(message)s') - log_ch = systemd.journal.JournalHandler() - log_ch.setFormatter(log_fmt) - log_adapter.addHandler(log_ch) - log_adapter.setLevel(logging.DEBUG) - - log_adapter.log(level, message) - class Logger: - def __init__(self, path: Path = Path('/var/log/archinstall')) -> None: - self._path = path + def __init__(self, path: Path | None = None) -> None: + if path is None: + path = Path('/var/log/archinstall') + + self._path: Path = path @property def path(self) -> Path: @@ -212,7 +150,7 @@ class Logger: self._check_permissions() with self.path.open('a') as f: - ts = _timestamp() + ts = timestamp() level_name = logging.getLevelName(level) f.write(f'[{ts}] - {level_name} - {content}\n') @@ -310,9 +248,20 @@ def _stylize_output( return f'\033[{ansi}m{text}\033[0m' -def _timestamp() -> str: - now = datetime.now(tz=UTC) - return now.strftime('%Y-%m-%d %H:%M:%S') +def journal_log(message: str, level: int = logging.DEBUG) -> None: + try: + import systemd.journal # type: ignore[import-not-found] + except ModuleNotFoundError: + return + + log_adapter = logging.getLogger('archinstall') + log_fmt = logging.Formatter('[%(levelname)s]: %(message)s') + log_ch = systemd.journal.JournalHandler() + log_ch.setFormatter(log_fmt) + log_adapter.addHandler(log_ch) + log_adapter.setLevel(logging.DEBUG) + + log_adapter.log(level, message) def info( @@ -376,7 +325,7 @@ def log( if _supports_color(): text = _stylize_output(text, fg, bg, reset, font) - Journald.log(text, level=level) + journal_log(text, level=level) if level != logging.DEBUG: print(text) diff --git a/archinstall/lib/utils/format.py b/archinstall/lib/utils/format.py new file mode 100644 index 00000000..3100a019 --- /dev/null +++ b/archinstall/lib/utils/format.py @@ -0,0 +1,47 @@ +from archinstall.tui.rich import BaseRichTable + + +def as_key_value_pair( + entries: dict[str, str | list[str] | bool], + ignore_empty: bool = True, +) -> str: + """ + Formats key-values as a Rich Table: + key1 : value1 + key2 : value2 + ... + """ + table = BaseRichTable() + table.add_column('key', style='bold', no_wrap=True) + table.add_column('value', style='white', max_width=70) + + for label, value in entries.items(): + if ignore_empty and not value: + continue + + if isinstance(value, bool): + value = 'Yes' if value else 'No' + + if isinstance(value, list): + value = '\n '.join(str(val) for val in value) + + table.add_row(label.title(), f': {value}') + + return table.stringify() + + +def as_columns(entries: list[str], cols: int) -> str: + """ + Will format a list into a given number of columns + """ + chunks: list[list[str]] = [] + output = '' + + for i in range(0, len(entries), cols): + chunks.append(entries[i : i + cols]) + + for row in chunks: + out_fmt = '{: <30} ' * len(row) + output += out_fmt.format(*row) + '\n' + + return output diff --git a/archinstall/lib/utils/util.py b/archinstall/lib/utils/util.py index 574cc8d5..f94ca18c 100644 --- a/archinstall/lib/utils/util.py +++ b/archinstall/lib/utils/util.py @@ -1,8 +1,14 @@ import secrets import string +from datetime import UTC, datetime -from archinstall.lib.output import FormattedOutput from archinstall.lib.pathnames import ARCHISO_MOUNTPOINT +from archinstall.lib.utils.format import as_columns + + +def timestamp() -> str: + now = datetime.now(tz=UTC) + return now.strftime('%Y-%m-%d %H:%M:%S') def running_from_iso() -> bool: @@ -36,7 +42,7 @@ def format_cols(items: list[str], header: str | None = None) -> str: else: col = 4 - text += FormattedOutput.as_columns(items, col) + text += as_columns(items, col) # remove whitespaces on each row text = '\n'.join(t.strip() for t in text.split('\n')) return text