style: satisfy the widened ruff default rule set

ruff 0.16 enables rules that earlier releases did not, so `ruff check .`
was already failing on HEAD with 35 findings - the CI job installs ruff
unpinned and would have gone red on the next push regardless of this
branch.

All changes are mechanical and behaviour-neutral:

- Optional[X] -> X | None, List[str] -> list[str], dropped the now unused
  typing imports (every module already carries
  `from __future__ import annotations`, and requires-python is >= 3.10).
- Sorted import blocks, `import automtu.x as x` -> `from automtu import x`.
- subprocess.run in pmtu.py and wg.py now passes check=False explicitly.
  That is the parameter default, so the calls behave exactly as before.
- int(round(x)) -> round(x): round() with a single argument already
  returns int.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-09-08 18:42:55 +02:00
parent 499e61346d
commit 6392131577
10 changed files with 25 additions and 32 deletions

View File

@@ -1,15 +1,13 @@
from __future__ import annotations from __future__ import annotations
import re import re
from typing import Optional
from .net import iface_exists, list_ifaces from .net import iface_exists, list_ifaces
_BRIDGE_RE = re.compile(r"^br-[0-9a-f]+$", re.IGNORECASE) _BRIDGE_RE = re.compile(r"^br-[0-9a-f]+$", re.IGNORECASE)
def _split_items(items: Optional[list[str]]) -> list[str]: def _split_items(items: list[str] | None) -> list[str]:
raw: list[str] = [] raw: list[str] = []
for item in items or []: for item in items or []:
raw.extend([x.strip() for x in item.split(",") if x.strip()]) raw.extend([x.strip() for x in item.split(",") if x.strip()])
@@ -18,7 +16,7 @@ def _split_items(items: Optional[list[str]]) -> list[str]:
def detect_docker_ifaces( def detect_docker_ifaces(
docker_if_args: Optional[list[str]], *, include_user_bridges: bool docker_if_args: list[str] | None, *, include_user_bridges: bool
) -> list[str]: ) -> list[str]:
""" """
Determine Docker-related interfaces to apply MTU to. Determine Docker-related interfaces to apply MTU to.

View File

@@ -4,19 +4,18 @@ from __future__ import annotations
import json import json
import sys import sys
from dataclasses import dataclass from dataclasses import dataclass
from typing import Optional
@dataclass(frozen=True) @dataclass(frozen=True)
class OutputMode: class OutputMode:
print_mtu: Optional[str] # "egress" | "effective" | "wg" | None print_mtu: str | None # "egress" | "effective" | "wg" | None
print_json: bool print_json: bool
@property @property
def machine(self) -> bool: def machine(self) -> bool:
return bool(self.print_mtu or self.print_json) return bool(self.print_mtu or self.print_json)
def validate(self) -> Optional[str]: def validate(self) -> str | None:
if self.print_mtu and self.print_json: if self.print_mtu and self.print_json:
return "--print-mtu and --print-json are mutually exclusive." return "--print-mtu and --print-json are mutually exclusive."
return None return None
@@ -67,24 +66,24 @@ def emit_json(
egress_iface: str, egress_iface: str,
base_mtu: int, base_mtu: int,
effective_mtu: int, effective_mtu: int,
egress_forced_mtu: Optional[int], egress_forced_mtu: int | None,
egress_applied: bool, egress_applied: bool,
pmtu_targets: list[str], pmtu_targets: list[str],
pmtu_auto_targets_added: list[str], pmtu_auto_targets_added: list[str],
pmtu_policy: str, pmtu_policy: str,
pmtu_chosen: Optional[int], pmtu_chosen: int | None,
pmtu_results: dict[str, Optional[int]], pmtu_results: dict[str, int | None],
wg_iface: str, wg_iface: str,
wg_mtu: int, wg_mtu: int,
wg_overhead: int, wg_overhead: int,
wg_min: int, wg_min: int,
wg_set_mtu: Optional[int], wg_set_mtu: int | None,
wg_clamped: bool, wg_clamped: bool,
wg_present: bool, wg_present: bool,
wg_active: bool, wg_active: bool,
wg_applied: bool, wg_applied: bool,
docker_ifaces: Optional[list[str]] = None, docker_ifaces: list[str] | None = None,
docker_applied: Optional[list[str]] = None, docker_applied: list[str] | None = None,
dry_run: bool, dry_run: bool,
) -> bool: ) -> bool:
""" """

View File

@@ -4,14 +4,12 @@ import shlex
import shutil import shutil
import subprocess import subprocess
from pathlib import Path from pathlib import Path
from typing import List
_SYSTEMD_UNIT_PATH = Path("/etc/systemd/system/automtu.service") _SYSTEMD_UNIT_PATH = Path("/etc/systemd/system/automtu.service")
_DOCKER_SYSTEMD_UNIT_PATH = Path("/etc/systemd/system/automtu-docker.service") _DOCKER_SYSTEMD_UNIT_PATH = Path("/etc/systemd/system/automtu-docker.service")
def _strip_persist_args(argv: List[str]) -> List[str]: def _strip_persist_args(argv: list[str]) -> list[str]:
""" """
Remove persistence-only arguments from argv: Remove persistence-only arguments from argv:
- --persist systemd|docker - --persist systemd|docker
@@ -51,7 +49,7 @@ def _resolve_exec(argv0: str) -> str:
return argv0 return argv0
def _needs_docker_ordering(filtered_argv: List[str]) -> bool: def _needs_docker_ordering(filtered_argv: list[str]) -> bool:
""" """
Heuristic: If we apply docker MTU (directly or via --apply-all), order after docker.service. Heuristic: If we apply docker MTU (directly or via --apply-all), order after docker.service.
""" """
@@ -115,7 +113,7 @@ def _uninstall_unit(unit_path: Path, *, dry: bool) -> None:
print(f"[automtu] Uninstalled systemd service: {unit_path.name}") print(f"[automtu] Uninstalled systemd service: {unit_path.name}")
def persist_systemd(argv: List[str], *, dry: bool) -> None: def persist_systemd(argv: list[str], *, dry: bool) -> None:
""" """
Install a systemd oneshot service that re-runs automtu with the same arguments. Install a systemd oneshot service that re-runs automtu with the same arguments.
Adds docker ordering automatically if docker MTU is applied. Adds docker ordering automatically if docker MTU is applied.
@@ -142,7 +140,7 @@ def uninstall_systemd(*, dry: bool) -> None:
_uninstall_unit(_SYSTEMD_UNIT_PATH, dry=dry) _uninstall_unit(_SYSTEMD_UNIT_PATH, dry=dry)
def persist_docker(argv: List[str], *, dry: bool) -> None: def persist_docker(argv: list[str], *, dry: bool) -> None:
""" """
Docker-focused persistence backend: Docker-focused persistence backend:
always orders after docker.service (even if args don't include docker flags), always orders after docker.service (even if args don't include docker flags),

View File

@@ -2,7 +2,6 @@ from __future__ import annotations
import ipaddress import ipaddress
import subprocess import subprocess
from typing import Optional
def _is_ipv6(target: str) -> bool: def _is_ipv6(target: str) -> bool:
@@ -14,7 +13,7 @@ def _is_ipv6(target: str) -> bool:
def _rc(cmd: list[str]) -> int: def _rc(cmd: list[str]) -> int:
return subprocess.run( return subprocess.run(
cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL cmd, check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
).returncode ).returncode
@@ -28,7 +27,7 @@ def _ping_ok(payload: int, target: str, timeout_s: float) -> bool:
"-s", "-s",
str(payload), str(payload),
"-W", "-W",
str(max(1, int(round(timeout_s)))), str(max(1, round(timeout_s))),
] ]
if _is_ipv6(target): if _is_ipv6(target):
cmd.insert(1, "-6") cmd.insert(1, "-6")
@@ -37,7 +36,7 @@ def _ping_ok(payload: int, target: str, timeout_s: float) -> bool:
def probe_pmtu( def probe_pmtu(
target: str, lo_payload: int = 1200, hi_payload: int = 1472, timeout: float = 1.0 target: str, lo_payload: int = 1200, hi_payload: int = 1472, timeout: float = 1.0
) -> Optional[int]: ) -> int | None:
hdr = 48 if _is_ipv6(target) else 28 hdr = 48 if _is_ipv6(target) else 28
if not _ping_ok(lo_payload, target, timeout): if not _ping_ok(lo_payload, target, timeout):

View File

@@ -2,7 +2,6 @@ from __future__ import annotations
import re import re
import subprocess import subprocess
from typing import List
from .net import iface_exists from .net import iface_exists
@@ -15,7 +14,7 @@ def _run(cmd: list[str]) -> str:
def _rc(cmd: list[str]) -> int: def _rc(cmd: list[str]) -> int:
return subprocess.run( return subprocess.run(
cmd, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL cmd, check=False, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL
).returncode ).returncode
@@ -23,7 +22,7 @@ def wg_is_active(wg_if: str) -> bool:
return iface_exists(wg_if) and _rc(["wg", "show", wg_if]) == 0 return iface_exists(wg_if) and _rc(["wg", "show", wg_if]) == 0
def wg_peer_endpoints(wg_if: str) -> List[str]: def wg_peer_endpoints(wg_if: str) -> list[str]:
targets: list[str] = [] targets: list[str] = []
out = _run(["wg", "show", wg_if, "endpoints"]) out = _run(["wg", "show", wg_if, "endpoints"])

View File

@@ -1,7 +1,7 @@
import unittest import unittest
from unittest.mock import patch from unittest.mock import patch
import automtu.docker as docker from automtu import docker
class TestDocker(unittest.TestCase): class TestDocker(unittest.TestCase):

View File

@@ -1,9 +1,9 @@
import io import io
import json import json
import unittest import unittest
from contextlib import redirect_stdout, redirect_stderr from contextlib import redirect_stderr, redirect_stdout
from automtu.output import OutputMode, emit_json, emit_single_number, Logger from automtu.output import Logger, OutputMode, emit_json, emit_single_number
class TestOutput(unittest.TestCase): class TestOutput(unittest.TestCase):

View File

@@ -4,7 +4,7 @@ from contextlib import redirect_stdout
from pathlib import Path from pathlib import Path
from unittest.mock import patch from unittest.mock import patch
import automtu.persist as persist from automtu import persist
class TestPersist(unittest.TestCase): class TestPersist(unittest.TestCase):

View File

@@ -1,7 +1,7 @@
import unittest import unittest
from unittest.mock import patch from unittest.mock import patch
import automtu.pmtu as pmtu from automtu import pmtu
class TestPmtu(unittest.TestCase): class TestPmtu(unittest.TestCase):

View File

@@ -1,7 +1,7 @@
import unittest import unittest
from unittest.mock import patch from unittest.mock import patch
import automtu.wg as wg from automtu import wg
class TestWg(unittest.TestCase): class TestWg(unittest.TestCase):