From 4ed53754141d8a1ef9087dc3ff4afba58fd8c1e0 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:19:53 -0400 Subject: [PATCH 1/9] Ignore os-path-abspath violation --- docs/conf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/conf.py b/docs/conf.py index ab52ef9a4a..dfd0d63837 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -6,7 +6,7 @@ if TYPE_CHECKING: from sphinx.application import Sphinx -sys.path.insert(0, os.path.abspath('..')) +sys.path.insert(0, os.path.abspath('..')) # noqa: PTH100 def process_docstring( From 2a801cdbe4a1623f941a7d1ba38d4a565c43df17 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:20:43 -0400 Subject: [PATCH 2/9] Ignore os-getcwd violations --- archinstall/lib/command.py | 2 +- test_tooling/qemu/qemu.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/archinstall/lib/command.py b/archinstall/lib/command.py index 177febfbbe..b55eecf770 100644 --- a/archinstall/lib/command.py +++ b/archinstall/lib/command.py @@ -191,7 +191,7 @@ def poll(self) -> None: def execute(self) -> bool: import pty - if (old_dir := os.getcwd()) != self.working_directory: + if (old_dir := os.getcwd()) != self.working_directory: # noqa: PTH109 os.chdir(str(self.working_directory)) # Note: If for any reason, we get a Python exception between here diff --git a/test_tooling/qemu/qemu.py b/test_tooling/qemu/qemu.py index ccf5cae7f7..23f048013b 100644 --- a/test_tooling/qemu/qemu.py +++ b/test_tooling/qemu/qemu.py @@ -312,7 +312,7 @@ def poll(self) -> None: def execute(self) -> bool: import pty - if (old_dir := os.getcwd()) != self.working_directory: + if (old_dir := os.getcwd()) != self.working_directory: # noqa: PTH109 os.chdir(str(self.working_directory)) # Note: If for any reason, we get a Python exception between here From 47b354d28b17a33b0764ee724eb323c996fd29c6 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:21:16 -0400 Subject: [PATCH 3/9] Fix os-path-isdir --- archinstall/lib/hardware.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index 8bb0520deb..e6c07999ab 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -1,4 +1,3 @@ -import os from dataclasses import dataclass from enum import Enum, StrEnum from functools import cached_property @@ -213,7 +212,7 @@ def has_wifi() -> bool: @staticmethod def has_uefi() -> bool: - return os.path.isdir('/sys/firmware/efi') + return Path('/sys/firmware/efi').is_dir() @staticmethod def _graphics_devices() -> dict[str, str]: From ec73f30ad569d345e2203a48d028ae6061b4de5e Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:21:57 -0400 Subject: [PATCH 4/9] Fix os-path-isfile --- archinstall/lib/plugins.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/archinstall/lib/plugins.py b/archinstall/lib/plugins.py index 4756e587c4..27e800ad21 100644 --- a/archinstall/lib/plugins.py +++ b/archinstall/lib/plugins.py @@ -65,7 +65,7 @@ def load_plugin(path: Path) -> None: namespace: str | None = None info(f'Loading plugin from {path}') - if os.path.isfile(path): + if path.is_file(): namespace = _import_via_path(path) if namespace and namespace in sys.modules: From 14897f756a4e6958ff53baed419faeacc7f11fc5 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:24:43 -0400 Subject: [PATCH 5/9] Fix os-path-basename --- archinstall/lib/plugins.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/archinstall/lib/plugins.py b/archinstall/lib/plugins.py index 27e800ad21..33d26889f1 100644 --- a/archinstall/lib/plugins.py +++ b/archinstall/lib/plugins.py @@ -1,5 +1,4 @@ import importlib.util -import os import sys from importlib import metadata from pathlib import Path @@ -34,7 +33,7 @@ def plugin(f: Any, *_args: Any, **_kwargs: Any) -> None: def _import_via_path(path: Path, namespace: str | None = None) -> str: if not namespace: - namespace = os.path.basename(path) + namespace = path.name if namespace == '__init__.py': namespace = path.parent.name From fae0f2051a92142ea67ce9c964c8fb0975546b36 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:26:21 -0400 Subject: [PATCH 6/9] Fix os-path-splitext --- archinstall/lib/installer.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index f6b0b2bcd1..df5a525268 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -2098,7 +2098,7 @@ def set_x11_keyboard_language(self, language: str) -> bool: return True def _service_started(self, service_name: str) -> str | None: - if os.path.splitext(service_name)[1] not in ('.service', '.target', '.timer'): + if Path(service_name).suffix not in ('.service', '.target', '.timer'): service_name += '.service' # Just to be safe last_execution_time = ( @@ -2116,7 +2116,7 @@ def _service_started(self, service_name: str) -> str | None: return last_execution_time def _service_state(self, service_name: str) -> str: - if os.path.splitext(service_name)[1] not in ('.service', '.target', '.timer'): + if Path(service_name).suffix not in ('.service', '.target', '.timer'): service_name += '.service' # Just to be safe return SysCommand( From 1f846f758f3defd6e8b612391794fa355c9885d6 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:28:02 -0400 Subject: [PATCH 7/9] Fix builtin-open --- .../default_profiles/desktops/awesome.py | 14 ++++---- archinstall/lib/disk/device_handler.py | 3 +- archinstall/lib/disk/luks.py | 2 +- archinstall/lib/hardware.py | 13 ++++--- archinstall/lib/installer.py | 34 +++++++++++-------- archinstall/lib/locale/utils.py | 2 +- archinstall/lib/profile/profiles_handler.py | 8 ++--- 7 files changed, 37 insertions(+), 39 deletions(-) diff --git a/archinstall/default_profiles/desktops/awesome.py b/archinstall/default_profiles/desktops/awesome.py index 73a0d419ba..a8b8539435 100644 --- a/archinstall/default_profiles/desktops/awesome.py +++ b/archinstall/default_profiles/desktops/awesome.py @@ -36,21 +36,20 @@ def install(self, install_session: Installer) -> None: super().install(install_session) # TODO: Copy a full configuration to ~/.config/awesome/rc.lua instead. - with open(f'{install_session.target}/etc/xdg/awesome/rc.lua') as fh: - awesome_lua = fh.read() + rc_lua = install_session.target / 'etc/xdg/awesome/rc.lua' + awesome_lua = rc_lua.read_text() # Replace xterm with alacritty for a smoother experience. awesome_lua = awesome_lua.replace('"xterm"', '"alacritty"') - with open(f'{install_session.target}/etc/xdg/awesome/rc.lua', 'w') as fh: - fh.write(awesome_lua) + rc_lua.write_text(awesome_lua) # TODO: Configure the right-click-menu to contain the above packages that were installed. (as a user config) # TODO: check if we selected a greeter, # but for now, awesome is intended to run without one. - with open(f'{install_session.target}/etc/X11/xinit/xinitrc') as xinitrc: - xinitrc_data = xinitrc.read() + xinitrc = install_session.target / 'etc/X11/xinit/xinitrc' + xinitrc_data = xinitrc.read_text() for line in xinitrc_data.split('\n'): if 'twm &' in line: @@ -63,5 +62,4 @@ def install(self, install_session: Installer) -> None: xinitrc_data += '\n' xinitrc_data += 'exec awesome\n' - with open(f'{install_session.target}/etc/X11/xinit/xinitrc', 'w') as xinitrc: - xinitrc.write(xinitrc_data) + xinitrc.write_text(xinitrc_data) diff --git a/archinstall/lib/disk/device_handler.py b/archinstall/lib/disk/device_handler.py index 88e08653e8..be6290bb76 100644 --- a/archinstall/lib/disk/device_handler.py +++ b/archinstall/lib/disk/device_handler.py @@ -616,8 +616,7 @@ def _wipe(self, dev_path: Path) -> None: @param dev_path: Device path of the partition to be wiped. @type dev_path: str """ - with open(dev_path, 'wb') as p: - p.write(bytearray(1024)) + dev_path.write_bytes(bytearray(1024)) def wipe_dev(self, block_device: BDevice) -> None: """ diff --git a/archinstall/lib/disk/luks.py b/archinstall/lib/disk/luks.py index 9aa9d353c3..6289c250ca 100644 --- a/archinstall/lib/disk/luks.py +++ b/archinstall/lib/disk/luks.py @@ -243,7 +243,7 @@ def _crypttab( ) -> None: debug(f'Adding crypttab entry for key {key_file}') - with open(crypttab_path, 'a') as crypttab: + with crypttab_path.open('a') as crypttab: opt = ','.join(options) uuid = self._get_luks_uuid() row = f'{self.mapper_name} UUID={uuid} {key_file} {opt}\n' diff --git a/archinstall/lib/hardware.py b/archinstall/lib/hardware.py index e6c07999ab..f2397e491f 100644 --- a/archinstall/lib/hardware.py +++ b/archinstall/lib/hardware.py @@ -9,6 +9,8 @@ from archinstall.lib.networking import enrich_iface_types, list_interfaces from archinstall.lib.translationhandler import tr +_VIRTUAL_DMI_ID = Path('/sys/devices/virtual/dmi/id') + class CPUVendor(StrEnum): AMD = 'AuthenticAMD' @@ -145,9 +147,8 @@ def __init__(self) -> None: def has_battery(self) -> bool: for type_path in Path('/sys/class/power_supply/').glob('*/type'): try: - with open(type_path) as f: - if f.read().strip() == 'Battery': - return True + if type_path.read_text().rstrip() == 'Battery': + return True except OSError: continue @@ -247,16 +248,14 @@ def cpu_model() -> str | None: @staticmethod def sys_vendor() -> str | None: try: - with open('/sys/devices/virtual/dmi/id/sys_vendor') as vendor: - return vendor.read().strip() + return (_VIRTUAL_DMI_ID / 'sys_vendor').read_text().rstrip() except FileNotFoundError: return None @staticmethod def product_name() -> str | None: try: - with open('/sys/devices/virtual/dmi/id/product_name') as product: - return product.read().strip() + return (_VIRTUAL_DMI_ID / 'product_name').read_text().rstrip() except FileNotFoundError: return None diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index df5a525268..4e99edbc1a 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -592,7 +592,7 @@ def set_mirrors( if repositories_config: debug(f'Pacman config: {repositories_config}') - with open(pacman_config, 'a') as fp: + with pacman_config.open('a') as fp: fp.write(repositories_config) regions_config = mirror_config.regions_config(mirror_list_handler, speed_sort=True) @@ -616,7 +616,7 @@ def genfstab(self, flags: str = '-pU') -> None: except SysCallError as err: raise RequirementError(f'Could not generate fstab, strapping in packages most likely failed (disk out of space?)\n Error: {err}') - with open(fstab_path, 'ab') as fp: + with fstab_path.open('ab') as fp: fp.write(gen_fstab) if not fstab_path.is_file(): @@ -627,7 +627,7 @@ def genfstab(self, flags: str = '-pU') -> None: if plugin.on_genfstab(self) is True: break - with open(fstab_path, 'a') as fp: + with fstab_path.open('a') as fp: for entry in self._fstab_entries: fp.write(f'{entry}\n') @@ -770,7 +770,7 @@ def configure_nic(self, nic: Nic) -> None: or conf ) - with open(f'{self.target}/etc/systemd/network/10-{nic.iface}.network', 'a') as netconf: + with (self.target / f'etc/systemd/network/10-{nic.iface}.network').open('a') as netconf: netconf.write(str(conf)) def systemd_resolved_stub_mode(self) -> None: @@ -833,7 +833,7 @@ def mkinitcpio(self, flags: list[str]) -> bool: if plugin.on_mkinitcpio(self): return True - with open(f'{self.target}/etc/mkinitcpio.conf', 'r+') as mkinit: + with (self.target / 'etc/mkinitcpio.conf').open('r+') as mkinit: content = mkinit.read() content = re.sub('\nMODULES=(.*)', f'\nMODULES=({" ".join(self._modules)})', content) content = re.sub('\nBINARIES=(.*)', f'\nBINARIES=({" ".join(self._binaries)})', content) @@ -1026,9 +1026,14 @@ def setup_swap(self, algo: ZramAlgorithm = ZramAlgorithm.ZSTD) -> None: info(f'Zram compression algorithm: {algo.value}') - with open(f'{self.target}/etc/systemd/zram-generator.conf', 'w') as zram_conf: - zram_conf.write('[zram0]\n') - zram_conf.write(f'compression-algorithm = {algo.value}\n') + (self.target / 'etc/systemd/zram-generator.conf').write_text( + textwrap.dedent( + f"""\ + [zram0] + compression-algorithm = {algo.value} + """, + ) + ) self.enable_service('systemd-zram-setup@zram0.service') @@ -1504,11 +1509,11 @@ def _add_limine_bootloader( if not bootloader_removable: # Create EFI boot menu entry for Limine. + fw_platform_size = Path('/sys/firmware/efi/fw_platform_size') try: - with open('/sys/firmware/efi/fw_platform_size') as fw_platform_size: - efi_bitness = fw_platform_size.read().strip() + efi_bitness = fw_platform_size.read_text().rstrip() except Exception as err: - raise OSError(f'Could not open or read /sys/firmware/efi/fw_platform_size to determine EFI bitness: {err}') + raise OSError(f'Could not open or read {fw_platform_size} to determine EFI bitness: {err}') if efi_bitness == '64': loader_path = f'\\EFI\\arch-limine\\{"BOOTAA64.EFI" if platform.machine() == "aarch64" else "BOOTX64.EFI"}' @@ -1790,9 +1795,8 @@ def _config_uki( raise ValueError(f'Could not detect ESP at mountpoint {self.target}') # Set up kernel command line - with open(self.target / 'etc/kernel/cmdline', 'w') as cmdline: - kernel_parameters = self._get_kernel_params(root) - cmdline.write(' '.join(kernel_parameters) + '\n') + kernel_parameters = self._get_kernel_params(root) + (self.target / 'etc/kernel/cmdline').write_text(' '.join(kernel_parameters) + '\n') diff_mountpoint = None @@ -1920,7 +1924,7 @@ def enable_sudo(self, user: User, group: bool = False) -> None: # Guarantees sudoer confs directory recommended perms sudoers_dir.chmod(0o440) # Appends a reference to the sudoers file, because if we are here sudoers.d did not exist yet - with open(self.target / 'etc/sudoers', 'a') as sudoers: + with (self.target / 'etc/sudoers').open('a') as sudoers: sudoers.write('@includedir /etc/sudoers.d\n') # We count how many files are there already so we know which number to prefix the file with diff --git a/archinstall/lib/locale/utils.py b/archinstall/lib/locale/utils.py index b53f124521..39393c75d7 100644 --- a/archinstall/lib/locale/utils.py +++ b/archinstall/lib/locale/utils.py @@ -21,7 +21,7 @@ def list_keyboard_languages() -> list[str]: def list_locales() -> list[str]: locales = [] - with open('/usr/share/i18n/SUPPORTED') as file: + with Path('/usr/share/i18n/SUPPORTED').open() as file: for line in file: if line != 'C.UTF-8 UTF-8\n': locales.append(line.rstrip()) diff --git a/archinstall/lib/profile/profiles_handler.py b/archinstall/lib/profile/profiles_handler.py index eb54671642..f1d9125865 100644 --- a/archinstall/lib/profile/profiles_handler.py +++ b/archinstall/lib/profile/profiles_handler.py @@ -189,13 +189,11 @@ def install_greeter(self, install_session: Installer, greeter: GreeterType) -> N # slick-greeter requires a config change if greeter == GreeterType.LightdmSlick: path = install_session.target.joinpath('etc/lightdm/lightdm.conf') - with open(path) as file: - filedata = file.read() + filedata = path.read_text() filedata = filedata.replace('#greeter-session=example-gtk-gnome', 'greeter-session=lightdm-slick-greeter') - with open(path, 'w') as file: - file.write(filedata) + path.write_text(filedata) if greeter == GreeterType.GreetdDms: greetd_config = install_session.target / 'etc/greetd/config.toml' @@ -306,7 +304,7 @@ def _is_legacy(self, file: Path) -> bool: Check if the provided profile file contains a legacy profile definition """ - with open(file) as fp: + with file.open() as fp: for line in fp.readlines(): if '__packages__' in line: return True From b0ba7fbfdda993cb7924a7e6322e15b401dffa55 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:28:59 -0400 Subject: [PATCH 8/9] Ignore os-listdir violations --- archinstall/lib/installer.py | 2 +- archinstall/lib/translationhandler.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/archinstall/lib/installer.py b/archinstall/lib/installer.py index 4e99edbc1a..417a87e5aa 100644 --- a/archinstall/lib/installer.py +++ b/archinstall/lib/installer.py @@ -1928,7 +1928,7 @@ def enable_sudo(self, user: User, group: bool = False) -> None: sudoers.write('@includedir /etc/sudoers.d\n') # We count how many files are there already so we know which number to prefix the file with - num_of_rules_already = len(os.listdir(sudoers_dir)) + num_of_rules_already = len(os.listdir(sudoers_dir)) # noqa: PTH208 file_num_str = f'{num_of_rules_already:02d}' # We want 00_user1, 01_user2, etc # Guarantees that username str does not contain invalid characters for a linux file name: diff --git a/archinstall/lib/translationhandler.py b/archinstall/lib/translationhandler.py index 73687003dc..c33fad6f72 100644 --- a/archinstall/lib/translationhandler.py +++ b/archinstall/lib/translationhandler.py @@ -241,7 +241,7 @@ def _provided_translations(self) -> list[str]: Get a list of all known languages """ translation_files = [] - for filename in os.listdir(self._locales_dir): + for filename in os.listdir(self._locales_dir): # noqa: PTH208 if len(filename) == 2 or filename in ['pt_BR', 'zh-CN', 'zh-TW']: translation_files.append(filename) From cf58445da3af0b3ae4d7f6dc5545622811694541 Mon Sep 17 00:00:00 2001 From: codefiles <11915375+codefiles@users.noreply.github.com> Date: Tue, 29 Sep 2026 19:29:47 -0400 Subject: [PATCH 9/9] Enable Ruff flake8-use-pathlib --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index b6e0391ce7..8db118fd1f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -207,6 +207,7 @@ select = [ "PLC", # Pylint conventions "PLE", # Pylint errors "PLW", # Pylint warnings + "PTH", # flake8-use-pathlib "PYI", # flake8-pyi "RET", # flake8-return "RSE", # flake8-raise