From f78104e1c8c7becf3d9a85bfdb935daed7cfc04d Mon Sep 17 00:00:00 2001 From: anti Date: Sun, 12 Apr 2026 02:17:50 -0400 Subject: [PATCH] fix: resolve all ruff lint errors and SQLite UNIQUE constraint issue MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ruff fixes (20 errors → 0): - F401: Remove unused imports (DeckyConfig, random_hostname, IniConfig, COMPOSE_FILE, sys, patch) across cli.py, mutator/engine.py, templates/ftp, templates/rdp, test_mysql.py, test_postgres.py - F541: Remove extraneous f-prefixes on strings with no placeholders in templates/imap, test_ftp_live, test_http_live - E741: Rename ambiguous variable 'l' to descriptive names (line, entry, part) across conftest.py, test_ftp_live, test_http_live, test_mongodb_live, test_pop3, test_ssh SQLite fix: - Change _initialize_sync() admin seeding from SELECT-then-INSERT to INSERT OR IGNORE, preventing IntegrityError when admin user already exists from a previous run --- decnet/cli.py | 4 +--- decnet/mutator/engine.py | 2 +- decnet/web/db/sqlite/repository.py | 31 +++++++++++--------------- templates/ftp/server.py | 1 - templates/imap/server.py | 2 +- templates/rdp/server.py | 1 - tests/live/conftest.py | 2 +- tests/live/test_ftp_live.py | 4 ++-- tests/live/test_http_live.py | 4 ++-- tests/live/test_mongodb_live.py | 2 +- tests/service_testing/test_mysql.py | 2 +- tests/service_testing/test_pop3.py | 6 ++--- tests/service_testing/test_postgres.py | 2 +- tests/test_ssh.py | 4 ++-- 14 files changed, 29 insertions(+), 38 deletions(-) diff --git a/decnet/cli.py b/decnet/cli.py index d3dc760..90bc1c2 100644 --- a/decnet/cli.py +++ b/decnet/cli.py @@ -24,13 +24,11 @@ from decnet.env import ( ) from decnet.archetypes import Archetype, all_archetypes, get_archetype from decnet.config import ( - DeckyConfig, DecnetConfig, - random_hostname, ) from decnet.distros import all_distros, get_distro from decnet.fleet import all_service_names, build_deckies, build_deckies_from_ini -from decnet.ini_loader import IniConfig, load_ini +from decnet.ini_loader import load_ini from decnet.network import detect_interface, detect_subnet, allocate_ips, get_host_ip from decnet.services.registry import all_services diff --git a/decnet/mutator/engine.py b/decnet/mutator/engine.py index fbd3096..eadbb70 100644 --- a/decnet/mutator/engine.py +++ b/decnet/mutator/engine.py @@ -13,7 +13,7 @@ from decnet.archetypes import get_archetype from decnet.fleet import all_service_names from decnet.composer import write_compose from decnet.config import DeckyConfig, load_state, save_state -from decnet.engine import COMPOSE_FILE, _compose_with_retry +from decnet.engine import _compose_with_retry import subprocess # nosec B404 diff --git a/decnet/web/db/sqlite/repository.py b/decnet/web/db/sqlite/repository.py index fa65f9f..a2cf745 100644 --- a/decnet/web/db/sqlite/repository.py +++ b/decnet/web/db/sqlite/repository.py @@ -33,25 +33,20 @@ class SQLiteRepository(BaseRepository): from decnet.web.db.sqlite.database import get_sync_engine engine = get_sync_engine(self.db_path) with engine.connect() as conn: - result = conn.execute( - text("SELECT uuid FROM users WHERE username = :u"), - {"u": DECNET_ADMIN_USER}, + conn.execute( + text( + "INSERT OR IGNORE INTO users (uuid, username, password_hash, role, must_change_password) " + "VALUES (:uuid, :u, :p, :r, :m)" + ), + { + "uuid": str(uuid.uuid4()), + "u": DECNET_ADMIN_USER, + "p": get_password_hash(DECNET_ADMIN_PASSWORD), + "r": "admin", + "m": 1, + }, ) - if not result.fetchone(): - conn.execute( - text( - "INSERT INTO users (uuid, username, password_hash, role, must_change_password) " - "VALUES (:uuid, :u, :p, :r, :m)" - ), - { - "uuid": str(uuid.uuid4()), - "u": DECNET_ADMIN_USER, - "p": get_password_hash(DECNET_ADMIN_PASSWORD), - "r": "admin", - "m": 1, - }, - ) - conn.commit() + conn.commit() async def initialize(self) -> None: """Async warm-up / verification.""" diff --git a/templates/ftp/server.py b/templates/ftp/server.py index 4ee959f..5c69c14 100644 --- a/templates/ftp/server.py +++ b/templates/ftp/server.py @@ -6,7 +6,6 @@ forwards events as JSON to LOG_TARGET if set. """ import os -import sys from pathlib import Path from twisted.internet import defer, reactor diff --git a/templates/imap/server.py b/templates/imap/server.py index fcc5ded..71489af 100644 --- a/templates/imap/server.py +++ b/templates/imap/server.py @@ -18,7 +18,7 @@ NODE_NAME = os.environ.get("NODE_NAME", "mailserver") SERVICE_NAME = "imap" LOG_TARGET = os.environ.get("LOG_TARGET", "") PORT = int(os.environ.get("PORT", "143")) -IMAP_BANNER = os.environ.get("IMAP_BANNER", f"* OK Dovecot ready.\r\n") +IMAP_BANNER = os.environ.get("IMAP_BANNER", "* OK Dovecot ready.\r\n") _RAW_USERS = os.environ.get("IMAP_USERS", "admin:admin123,root:toor,mail:mail,user:user") VALID_USERS: dict[str, str] = { diff --git a/templates/rdp/server.py b/templates/rdp/server.py index e669499..12a0a48 100644 --- a/templates/rdp/server.py +++ b/templates/rdp/server.py @@ -7,7 +7,6 @@ LOG_TARGET if set. """ import os -import sys from twisted.internet import protocol, reactor from twisted.python import log as twisted_log diff --git a/tests/live/conftest.py b/tests/live/conftest.py index 6457326..0626a00 100644 --- a/tests/live/conftest.py +++ b/tests/live/conftest.py @@ -83,7 +83,7 @@ def assert_rfc5424( criteria = {"service": service, "event_type": event_type, **fields} raise AssertionError( f"No RFC 5424 line matching {criteria!r} found among {len(lines)} lines:\n" - + "\n".join(f" {l!r}" for l in lines[:20]) + + "\n".join(f" {line!r}" for line in lines[:20]) ) diff --git a/tests/live/test_ftp_live.py b/tests/live/test_ftp_live.py index 86e591c..3d1c876 100644 --- a/tests/live/test_ftp_live.py +++ b/tests/live/test_ftp_live.py @@ -35,5 +35,5 @@ class TestFTPLive: ftp.close() lines = drain() # At least one RFC 5424 line from the ftp service - rfc_lines = [l for l in lines if "<" in l and ">1 " in l and "ftp" in l] - assert rfc_lines, f"No ftp RFC 5424 lines found. stdout:\n" + "\n".join(lines[:15]) + rfc_lines = [line for line in lines if "<" in line and ">1 " in line and "ftp" in line] + assert rfc_lines, "No ftp RFC 5424 lines found. stdout:\n" + "\n".join(lines[:15]) diff --git a/tests/live/test_http_live.py b/tests/live/test_http_live.py index 2d7cce4..ec59cb3 100644 --- a/tests/live/test_http_live.py +++ b/tests/live/test_http_live.py @@ -28,8 +28,8 @@ class TestHTTPLive: ) lines = drain() # body field present in log line - assert any("body=" in l for l in lines if "request" in l), ( - f"Expected 'body=' in request log line. Got:\n" + "\n".join(lines[:10]) + assert any("body=" in line for line in lines if "request" in line), ( + "Expected 'body=' in request log line. Got:\n" + "\n".join(lines[:10]) ) def test_method_and_path_in_log(self, live_service): diff --git a/tests/live/test_mongodb_live.py b/tests/live/test_mongodb_live.py index 4466d3d..3a2dd05 100644 --- a/tests/live/test_mongodb_live.py +++ b/tests/live/test_mongodb_live.py @@ -65,6 +65,6 @@ class TestMongoDBLive: client.close() lines = drain() # At least one message was exchanged - assert any("mongodb" in l for l in lines), ( + assert any("mongodb" in line for line in lines), ( "Expected at least one mongodb log line" ) diff --git a/tests/service_testing/test_mysql.py b/tests/service_testing/test_mysql.py index 5379b3a..e575570 100644 --- a/tests/service_testing/test_mysql.py +++ b/tests/service_testing/test_mysql.py @@ -8,7 +8,7 @@ length fields that could cause huge buffer allocations. import importlib.util import struct import sys -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest from hypothesis import given, settings diff --git a/tests/service_testing/test_pop3.py b/tests/service_testing/test_pop3.py index cde8a93..9543bbc 100644 --- a/tests/service_testing/test_pop3.py +++ b/tests/service_testing/test_pop3.py @@ -176,7 +176,7 @@ def test_pop3_list_returns_10_entries(pop3_mod): resp = _replies(written).decode() assert resp.startswith("+OK 10") # Count individual message lines: "N size\r\n" - entries = [l for l in resp.split("\r\n") if l and l[0].isdigit()] + entries = [entry for entry in resp.split("\r\n") if entry and entry[0].isdigit()] assert len(entries) == 10 @@ -225,7 +225,7 @@ def test_pop3_top_3_body_lines_count(pop3_mod): parts = resp.split("\r\n\r\n", 1) assert len(parts) == 2 body_section = parts[1].rstrip("\r\n.") - body_lines = [l for l in body_section.split("\r\n") if l != "."] + body_lines = [part for part in body_section.split("\r\n") if part != "."] assert len(body_lines) <= 3 @@ -235,7 +235,7 @@ def test_pop3_uidl_returns_10_entries(pop3_mod): _send(proto, "UIDL") resp = _replies(written).decode() assert resp.startswith("+OK") - entries = [l for l in resp.split("\r\n") if l and l[0].isdigit()] + entries = [entry for entry in resp.split("\r\n") if entry and entry[0].isdigit()] assert len(entries) == 10 diff --git a/tests/service_testing/test_postgres.py b/tests/service_testing/test_postgres.py index e2220ba..e69a4fa 100644 --- a/tests/service_testing/test_postgres.py +++ b/tests/service_testing/test_postgres.py @@ -8,7 +8,7 @@ tests for zero/tiny/huge msg_len in both the startup and auth states. import importlib.util import struct import sys -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock import pytest from hypothesis import given, settings diff --git a/tests/test_ssh.py b/tests/test_ssh.py index 65ccb7e..1573912 100644 --- a/tests/test_ssh.py +++ b/tests/test_ssh.py @@ -112,8 +112,8 @@ def test_dockerfile_has_rsyslog(): def test_dockerfile_runs_as_root(): - lines = [l.strip() for l in _dockerfile_text().splitlines()] - user_lines = [l for l in lines if l.startswith("USER ")] + lines = [line.strip() for line in _dockerfile_text().splitlines()] + user_lines = [line for line in lines if line.startswith("USER ")] assert user_lines == [], f"Unexpected USER directive(s): {user_lines}"