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:
@@ -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.
|
||||||
|
|||||||
@@ -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:
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -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),
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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"])
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
Reference in New Issue
Block a user