Release 1.2.1: auto-select single NIC
Release / build (push) Has been cancelled

- Auto-select the network adapter when only one is found (configurable via auto_select_single; asked on first run)
This commit is contained in:
2026-06-03 17:55:52 +03:00
parent 876b2c72bc
commit 979df127a6
3 changed files with 45 additions and 12 deletions
+6 -2
View File
@@ -18,7 +18,7 @@ from .update_check import check_for_update
from .network import list_adapters, set_static_ip, revert_to_dhcp, get_current_ipv4 from .network import list_adapters, set_static_ip, revert_to_dhcp, get_current_ipv4
def _pick_adapter(console: Console) -> dict | None: def _pick_adapter(console: Console, auto_single: bool = True) -> dict | None:
adapters = list_adapters() adapters = list_adapters()
if not adapters: if not adapters:
console.print(f"[red]{t('no_adapters')}[/]") console.print(f"[red]{t('no_adapters')}[/]")
@@ -29,6 +29,10 @@ def _pick_adapter(console: Console) -> dict | None:
ip = a.get("IPv4") or "" ip = a.get("IPv4") or ""
console.print(f" {i}) [{a['Status']:<12}] {a['Name']} ({a['Description']}) {ip}") console.print(f" {i}) [{a['Status']:<12}] {a['Name']} ({a['Description']}) {ip}")
if auto_single and len(adapters) == 1:
console.print(f"[green]{t('only_adapter', name=adapters[0]['Name'])}[/]")
return adapters[0]
while True: while True:
s = Prompt.ask(t("select_adapter")).strip() s = Prompt.ask(t("select_adapter")).strip()
if s.isdigit() and 1 <= int(s) <= len(adapters): if s.isdigit() and 1 <= int(s) <= len(adapters):
@@ -80,7 +84,7 @@ def main() -> None:
console.print(title) console.print(title)
console.print() console.print()
nic = _pick_adapter(console) nic = _pick_adapter(console, cfg_data.get("auto_select_single", True))
if not nic: if not nic:
input(t("press_enter")); return input(t("press_enter")); return
+37 -10
View File
@@ -19,16 +19,25 @@ CONFIG_HEADER = """\
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# netswitch configuration # netswitch configuration
# #
# To change the interface language, edit the 'language' value below. # language : interface language. Valid: en, ru
# Valid values: en, ru # auto_select_single : auto-pick the network adapter when only one is found,
# without asking (yes/no).
# #
# Чтобы сменить язык интерфейса, измените значение 'language' ниже. # language : язык интерфейса. Допустимо: en, ru
# Допустимые значения: en, ru # auto_select_single : автоматически выбирать сетевой адаптер, если он
# единственный, не спрашивая (yes/no).
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
""" """
def _to_bool(s: str, default: bool) -> bool:
s = (s or "").strip().lower()
if s in ("yes", "true", "y", "1", "on"): return True
if s in ("no", "false", "n", "0", "off"): return False
return default
def app_dir() -> Path: def app_dir() -> Path:
"""Directory holding the running executable (or source folder when run via python).""" """Directory holding the running executable (or source folder when run via python)."""
if getattr(sys, "frozen", False): if getattr(sys, "frozen", False):
@@ -57,10 +66,26 @@ def _ask_language() -> str:
print("Please enter 1 or 2 / Введите 1 или 2") print("Please enter 1 or 2 / Введите 1 или 2")
def _write_config(lang: str) -> None: def _ask_auto_select() -> bool:
"""First-run prompt — auto-select a lone adapter? Bilingual stdin."""
print()
print("Auto-select the network adapter when only one is found? (y/n)")
print("Автовыбор сетевого адаптера, если он единственный? (y/n)")
while True:
try:
c = input("> ").strip().lower()
except (EOFError, KeyboardInterrupt):
return True
if c in ("y", "yes", "д", "да", "1"): return True
if c in ("n", "no", "н", "нет", "0"): return False
print("y / n")
def _write_config(lang: str, auto_select: bool) -> None:
path = config_path() path = config_path()
cp = configparser.ConfigParser() cp = configparser.ConfigParser()
cp["General"] = {"language": lang} cp["General"] = {"language": lang,
"auto_select_single": "yes" if auto_select else "no"}
with path.open("w", encoding="utf-8") as f: with path.open("w", encoding="utf-8") as f:
f.write(CONFIG_HEADER) f.write(CONFIG_HEADER)
cp.write(f) cp.write(f)
@@ -70,19 +95,21 @@ def load_config() -> dict:
path = config_path() path = config_path()
if not path.exists(): if not path.exists():
lang = _ask_language() lang = _ask_language()
auto = _ask_auto_select()
try: try:
_write_config(lang) _write_config(lang, auto)
except OSError: except OSError:
pass pass
return {"language": lang} return {"language": lang, "auto_select_single": auto}
cp = configparser.ConfigParser() cp = configparser.ConfigParser()
try: try:
cp.read(path, encoding="utf-8") cp.read(path, encoding="utf-8")
except (configparser.Error, OSError): except (configparser.Error, OSError):
return {"language": DEFAULT_LANG} return {"language": DEFAULT_LANG, "auto_select_single": True}
lang = (cp.get("General", "language", fallback=DEFAULT_LANG) or DEFAULT_LANG).strip().lower() lang = (cp.get("General", "language", fallback=DEFAULT_LANG) or DEFAULT_LANG).strip().lower()
if lang not in SUPPORTED_LANGS: if lang not in SUPPORTED_LANGS:
lang = DEFAULT_LANG lang = DEFAULT_LANG
return {"language": lang} auto = _to_bool(cp.get("General", "auto_select_single", fallback="yes"), True)
return {"language": lang, "auto_select_single": auto}
+2
View File
@@ -14,6 +14,7 @@ STRINGS: dict[str, dict[str, str]] = {
"no_adapters": "No physical wired adapters found.", "no_adapters": "No physical wired adapters found.",
"press_enter": "Press Enter to exit", "press_enter": "Press Enter to exit",
"available_adapters": "Available adapters:", "available_adapters": "Available adapters:",
"only_adapter": "Only one adapter, auto-selected: {name}",
"select_adapter": "Select adapter number", "select_adapter": "Select adapter number",
"invalid_selection": "Invalid selection.", "invalid_selection": "Invalid selection.",
"selected": "Selected: {name}", "selected": "Selected: {name}",
@@ -40,6 +41,7 @@ STRINGS: dict[str, dict[str, str]] = {
"no_adapters": "Подходящие проводные адаптеры не найдены.", "no_adapters": "Подходящие проводные адаптеры не найдены.",
"press_enter": "Нажмите Enter для выхода", "press_enter": "Нажмите Enter для выхода",
"available_adapters": "Доступные адаптеры:", "available_adapters": "Доступные адаптеры:",
"only_adapter": "Адаптер один, выбран автоматически: {name}",
"select_adapter": "Введите номер адаптера", "select_adapter": "Введите номер адаптера",
"invalid_selection": "Неверный выбор.", "invalid_selection": "Неверный выбор.",
"selected": "Выбрано: {name}", "selected": "Выбрано: {name}",