refactor: remove noqa comments from miscellaneous scripts

- Fix underlying lint issues instead of suppressing with noqa
- Files: moviepy_showcase, pomodoro-wake-daemon, brother_printer,
  http_status_anki, geo_data, repo_explorer, steam_backlog_enforcer,
  music_generator
This commit is contained in:
Krzysztof kuhy Rudnicki 2026-03-13 20:48:40 +01:00
parent 078a4c0071
commit 0d47f77ee5
11 changed files with 161 additions and 106 deletions

View File

@ -28,16 +28,7 @@ import shutil
import tempfile import tempfile
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import numpy as np from moviepy import (
if TYPE_CHECKING:
from collections.abc import Callable
logger = logging.getLogger(__name__)
os.environ["FFMPEG_BINARY"] = "/usr/bin/ffmpeg"
from moviepy import ( # noqa: E402
AudioArrayClip, AudioArrayClip,
AudioClip, AudioClip,
BitmapClip, BitmapClip,
@ -53,7 +44,7 @@ from moviepy import ( # noqa: E402
concatenate_audioclips, concatenate_audioclips,
concatenate_videoclips, concatenate_videoclips,
) )
from moviepy.audio.fx import ( # noqa: E402 from moviepy.audio.fx import (
AudioDelay, AudioDelay,
AudioFadeIn, AudioFadeIn,
AudioFadeOut, AudioFadeOut,
@ -62,10 +53,10 @@ from moviepy.audio.fx import ( # noqa: E402
MultiplyStereoVolume, MultiplyStereoVolume,
MultiplyVolume, MultiplyVolume,
) )
from moviepy.video.compositing.CompositeVideoClip import ( # noqa: E402 from moviepy.video.compositing.CompositeVideoClip import (
clips_array, clips_array,
) )
from moviepy.video.fx import ( # noqa: E402 from moviepy.video.fx import (
AccelDecel, AccelDecel,
BlackAndWhite, BlackAndWhite,
Blink, Blink,
@ -99,11 +90,19 @@ from moviepy.video.fx import ( # noqa: E402
TimeMirror, TimeMirror,
TimeSymmetrize, TimeSymmetrize,
) )
from moviepy.video.tools.drawing import ( # noqa: E402 from moviepy.video.tools.drawing import (
circle, circle,
color_gradient, color_gradient,
color_split, color_split,
) )
import numpy as np
if TYPE_CHECKING:
from collections.abc import Callable
logger = logging.getLogger(__name__)
os.environ["FFMPEG_BINARY"] = "/usr/bin/ffmpeg"
# ── Constants ───────────────────────────────────────────────────── # ── Constants ─────────────────────────────────────────────────────
W, H = 1920, 1080 W, H = 1920, 1080
@ -473,30 +472,26 @@ def part2_clip_methods() -> list[VideoClip]:
# ══════════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════════
# PART 3 — Video Effects (all 34) # PART 3 — Video Effects (all 34)
# ══════════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════════
def part3_video_effects() -> list[VideoClip]: # noqa: PLR0915 def _fx(effect: object, label: str, dur: float = CLIP_DUR) -> VideoClip:
"""Demonstrate all 34 video effects.""" """Apply effect to base clip and label it."""
scenes: list[VideoClip] = [ b = _base_clip(dur)
_section_header( try:
"Part 3: Video Effects", result = b.with_effects([effect])
"All 34 effects from moviepy.video.fx", # Ensure it has a finite duration
), if result.duration is None or result.duration <= 0:
] result = result.with_duration(dur)
result = result.with_duration(min(result.duration, dur))
except (ValueError, OSError, AttributeError):
result = b
# Make sure it fits the canvas
if result.size != (W, H):
result = _resize_to_canvas(result)
return _titled(result, label)
def _fx(effect: object, label: str, dur: float = CLIP_DUR) -> VideoClip:
"""Apply effect to base clip and label it.""" def _part3_effects_1_to_17() -> list[VideoClip]:
b = _base_clip(dur) """Video effects 1-17: AccelDecel through MakeLoopable."""
try: scenes: list[VideoClip] = []
result = b.with_effects([effect])
# Ensure it has a finite duration
if result.duration is None or result.duration <= 0:
result = result.with_duration(dur)
result = result.with_duration(min(result.duration, dur))
except (ValueError, OSError, AttributeError):
result = b
# Make sure it fits the canvas
if result.size != (W, H):
result = _resize_to_canvas(result)
return _titled(result, label)
# 1. AccelDecel # 1. AccelDecel
scenes.append( scenes.append(
@ -577,8 +572,8 @@ def part3_video_effects() -> list[VideoClip]: # noqa: PLR0915
scenes.append( scenes.append(
_fx( _fx(
HeadBlur( HeadBlur(
fx=lambda t: W // 2, # noqa: ARG005 fx=lambda _: W // 2,
fy=lambda t: H // 2, # noqa: ARG005 fy=lambda _: H // 2,
radius=100, radius=100,
intensity=None, intensity=None,
), ),
@ -607,6 +602,13 @@ def part3_video_effects() -> list[VideoClip]: # noqa: PLR0915
_fx(MakeLoopable(overlap_duration=0.5), "MakeLoopable(overlap_duration=0.5)") _fx(MakeLoopable(overlap_duration=0.5), "MakeLoopable(overlap_duration=0.5)")
) )
return scenes
def _part3_effects_18_to_34() -> list[VideoClip]:
"""Video effects 18-34: Margin through TimeSymmetrize."""
scenes: list[VideoClip] = []
# 18. Margin # 18. Margin
b_margin = _base_clip().with_effects( b_margin = _base_clip().with_effects(
[ [
@ -737,6 +739,19 @@ def part3_video_effects() -> list[VideoClip]: # noqa: PLR0915
return scenes return scenes
def part3_video_effects() -> list[VideoClip]:
"""Demonstrate all 34 video effects."""
scenes: list[VideoClip] = [
_section_header(
"Part 3: Video Effects",
"All 34 effects from moviepy.video.fx",
),
]
scenes.extend(_part3_effects_1_to_17())
scenes.extend(_part3_effects_18_to_34())
return scenes
# ══════════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════════
# PART 4 — Audio # PART 4 — Audio
# ══════════════════════════════════════════════════════════════════ # ══════════════════════════════════════════════════════════════════

View File

@ -36,6 +36,9 @@ logging.basicConfig(
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
MIN_DEVICE_PARTS = 2
def is_app_running() -> bool: def is_app_running() -> bool:
"""Check whether the Pomodoro app is running locally.""" """Check whether the Pomodoro app is running locally."""
pgrep = shutil.which("pgrep") pgrep = shutil.which("pgrep")
@ -88,7 +91,7 @@ def get_adb_devices() -> list[str]:
devices: list[str] = [] devices: list[str] = []
for line in result.stdout.strip().splitlines()[1:]: for line in result.stdout.strip().splitlines()[1:]:
parts = line.split() parts = line.split()
if len(parts) >= 2 and parts[1] == "device": # noqa: PLR2004 if len(parts) >= MIN_DEVICE_PARTS and parts[1] == "device":
devices.append(parts[0]) devices.append(parts[0])
return devices return devices

View File

@ -60,6 +60,7 @@ TONER_RATED_PAGES = 1000
DRUM_RATED_PAGES = 10000 DRUM_RATED_PAGES = 10000
CUPS_PAGE_LOG = Path("/var/log/cups/page_log") CUPS_PAGE_LOG = Path("/var/log/cups/page_log")
CONSUMABLE_STATE_FILE = Path.home() / ".config" / "brother_printer" / "state.json" CONSUMABLE_STATE_FILE = Path.home() / ".config" / "brother_printer" / "state.json"
MIN_LPSTAT_JOB_PARTS = 4
def _out(text: str = "") -> None: def _out(text: str = "") -> None:
@ -250,7 +251,7 @@ def find_brother_usb() -> str:
return "" return ""
try: try:
r = subprocess.run( r = subprocess.run(
["lsusb"], # noqa: S607 ["/usr/bin/lsusb"],
capture_output=True, capture_output=True,
text=True, text=True,
timeout=5, timeout=5,
@ -285,7 +286,7 @@ def get_printer_info_from_cups() -> dict[str, str]:
info: dict[str, str] = {"product": "", "serial": ""} info: dict[str, str] = {"product": "", "serial": ""}
try: try:
r = subprocess.run( r = subprocess.run(
["lpstat", "-v"], # noqa: S607 ["/usr/bin/lpstat", "-v"],
capture_output=True, capture_output=True,
text=True, text=True,
timeout=5, timeout=5,
@ -488,7 +489,7 @@ def _get_pyusb_device_info() -> dict[str, str]:
dev = usb.core.find(idVendor=BROTHER_USB_VENDOR_ID) dev = usb.core.find(idVendor=BROTHER_USB_VENDOR_ID)
if dev is None: if dev is None:
return {} return {}
except Exception: # noqa: BLE001 except (ImportError, OSError, ValueError):
return {} return {}
else: else:
return { return {
@ -601,7 +602,7 @@ def _query_usb_port_status_raw() -> USBPortStatus | None:
finally: finally:
usb.util.release_interface(dev, 0) usb.util.release_interface(dev, 0)
usb.util.dispose_resources(dev) usb.util.dispose_resources(dev)
except Exception: # noqa: BLE001 except (OSError, ValueError):
logger.debug("USB port status query failed", exc_info=True) logger.debug("USB port status query failed", exc_info=True)
return None return None
finally: finally:
@ -1001,7 +1002,7 @@ def _parse_lpstat_jobs(output: str, printer_name: str) -> list[CUPSJob]:
if not line.startswith(printer_name): if not line.startswith(printer_name):
continue continue
parts = line.split() parts = line.split()
if len(parts) >= 4: # noqa: PLR2004 if len(parts) >= MIN_LPSTAT_JOB_PARTS:
job_id = parts[0] job_id = parts[0]
user = parts[1] user = parts[1]
size = parts[2] size = parts[2]
@ -1319,28 +1320,55 @@ def _offer_queue_fix(queue: CUPSQueueStatus) -> None:
_handle_backend_errors_only(choice) _handle_backend_errors_only(choice)
def _handle_disabled_with_jobs(queue: CUPSQueueStatus, choice: str) -> None: # noqa: C901 def _dwj_enable_only(printer_name: str) -> None:
"""Choice 1: re-enable printer so queued jobs are retried."""
if _cups_enable_printer(printer_name):
_out(f" {GREEN}✓ Printer re-enabled. Jobs will be retried.{RESET}")
def _dwj_cancel_and_enable(printer_name: str) -> None:
"""Choice 2: cancel all jobs then re-enable."""
_cups_cancel_all_jobs(printer_name)
if _cups_enable_printer(printer_name):
_out(f" {GREEN}✓ All jobs cancelled and printer re-enabled.{RESET}")
def _dwj_cancel_only(printer_name: str) -> None:
"""Choice 3: cancel all jobs."""
if _cups_cancel_all_jobs(printer_name):
_out(f" {GREEN}✓ All jobs cancelled.{RESET}")
def _dwj_restart_only(_printer_name: str) -> None:
"""Choice 4: restart CUPS."""
if _cups_restart_service():
_out(f" {GREEN}✓ CUPS restarted.{RESET}")
def _dwj_restart_and_enable(printer_name: str) -> None:
"""Choice 5: restart CUPS and re-enable printer."""
if _cups_restart_service():
_cups_enable_printer(printer_name)
_out(
f" {GREEN}✓ CUPS restarted, printer re-enabled."
f" Jobs will be retried.{RESET}"
)
_DWJ_ACTIONS: dict[str, Callable[[str], None]] = {
"1": _dwj_enable_only,
"2": _dwj_cancel_and_enable,
"3": _dwj_cancel_only,
"4": _dwj_restart_only,
"5": _dwj_restart_and_enable,
}
def _handle_disabled_with_jobs(queue: CUPSQueueStatus, choice: str) -> None:
"""Handle fix for disabled printer with pending jobs.""" """Handle fix for disabled printer with pending jobs."""
if choice == "1": action = _DWJ_ACTIONS.get(choice)
if _cups_enable_printer(queue.printer_name): if action is not None:
_out(f" {GREEN}✓ Printer re-enabled. Jobs will be retried.{RESET}") action(queue.printer_name)
elif choice == "2":
_cups_cancel_all_jobs(queue.printer_name)
if _cups_enable_printer(queue.printer_name):
_out(f" {GREEN}✓ All jobs cancelled and printer re-enabled.{RESET}")
elif choice == "3":
if _cups_cancel_all_jobs(queue.printer_name):
_out(f" {GREEN}✓ All jobs cancelled.{RESET}")
elif choice == "4":
if _cups_restart_service():
_out(f" {GREEN}✓ CUPS restarted.{RESET}")
elif choice == "5":
if _cups_restart_service():
_cups_enable_printer(queue.printer_name)
_out(
f" {GREEN}✓ CUPS restarted, printer re-enabled."
f" Jobs will be retried.{RESET}"
)
else: else:
_out(f" {DIM}No changes made.{RESET}") _out(f" {DIM}No changes made.{RESET}")

View File

@ -13,6 +13,7 @@ import hashlib
import logging import logging
from pathlib import Path from pathlib import Path
import sys import sys
import tempfile
from typing import TYPE_CHECKING from typing import TYPE_CHECKING
import genanki import genanki
@ -357,7 +358,7 @@ class _DeckBuilder:
filename = f"http_cat_{status_code}.jpg" filename = f"http_cat_{status_code}.jpg"
# Save to temp directory for genanki # Save to temp directory for genanki
temp_path = Path(f"/tmp/{filename}") # noqa: S108 temp_path = Path(tempfile.gettempdir()) / filename
temp_path.write_bytes(image_data) temp_path.write_bytes(image_data)
self.media_files.append(str(temp_path)) self.media_files.append(str(temp_path))

View File

@ -235,7 +235,10 @@ def _download_github_geojson(url: str, cache_path: Path) -> gpd.GeoDataFrame:
return gpd.read_file(cache_path) return gpd.read_file(cache_path)
sys.stdout.write(f"Downloading from {url}...\n") sys.stdout.write(f"Downloading from {url}...\n")
with urlopen(url, timeout=REQUEST_TIMEOUT) as response: # noqa: S310 if not url.startswith(("http://", "https://")):
msg = f"Unsupported URL scheme: {url}"
raise ValueError(msg)
with urlopen(url, timeout=REQUEST_TIMEOUT) as response:
data = json.loads(response.read().decode()) data = json.loads(response.read().decode())
_ensure_cache_dir() _ensure_cache_dir()

View File

@ -39,28 +39,21 @@ def check_dependencies(*, include_bark: bool = False) -> bool:
Args: Args:
include_bark: Whether to check for Bark dependencies as well. include_bark: Whether to check for Bark dependencies as well.
""" """
import importlib.util
missing = [] missing = []
try: if importlib.util.find_spec("torch") is None:
import torch # noqa: F401
except ImportError:
missing.append("torch") missing.append("torch")
try: if importlib.util.find_spec("transformers") is None:
import transformers # noqa: F401
except ImportError:
missing.append("transformers") missing.append("transformers")
try: if importlib.util.find_spec("scipy") is None:
import scipy # noqa: F401
except ImportError:
missing.append("scipy") missing.append("scipy")
if include_bark: if include_bark and importlib.util.find_spec("bark") is None:
try: missing.append("git+https://github.com/suno-ai/bark.git")
from bark import generate_audio as _bark_gen # noqa: F401
except ImportError:
missing.append("git+https://github.com/suno-ai/bark.git")
if missing: if missing:
print("Missing dependencies. Install with:") print("Missing dependencies. Install with:")

View File

@ -469,7 +469,7 @@ class RepoExplorer(tk.Tk):
fcntl.fcntl(master_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK) fcntl.fcntl(master_fd, fcntl.F_SETFL, fl | os.O_NONBLOCK)
self._proc = subprocess.Popen( self._proc = subprocess.Popen(
["bash", "run.sh", *extra], # noqa: S607 ["/usr/bin/bash", "run.sh", *extra],
cwd=path, cwd=path,
stdin=slave_fd, stdin=slave_fd,
stdout=slave_fd, stdout=slave_fd,
@ -485,7 +485,27 @@ class RepoExplorer(tk.Tk):
threading.Thread(target=self._read_pty, daemon=True).start() threading.Thread(target=self._read_pty, daemon=True).start()
threading.Thread(target=self._wait_proc, daemon=True).start() threading.Thread(target=self._wait_proc, daemon=True).start()
def _read_pty(self) -> None: # noqa: C901, PLR0912 @staticmethod
def _decode_buf(buf: bytes) -> str:
"""Decode a byte buffer, strip ANSI codes and carriage returns."""
return _strip_ansi(buf.decode("utf-8", errors="replace").replace("\r", ""))
def _flush_partial_buf(self, buf: bytes) -> None:
"""Flush a partial (no trailing newline) buffer to output."""
text = self._decode_buf(buf)
if text:
self._write_output(text)
def _process_complete_lines(self, buf: bytes) -> bytes:
"""Split buf on newlines, output complete lines, return remainder."""
while b"\n" in buf:
line, buf = buf.split(b"\n", 1)
text = self._decode_buf(line)
if text:
self._write_output(text + "\n")
return buf
def _read_pty(self) -> None:
"""Stream PTY output to the widget, stripping ANSI codes. """Stream PTY output to the widget, stripping ANSI codes.
Partial lines (prompts without a trailing newline) are flushed after Partial lines (prompts without a trailing newline) are flushed after
@ -503,11 +523,7 @@ class RepoExplorer(tk.Tk):
if buf: if buf:
idle_ticks += 1 idle_ticks += 1
if idle_ticks >= self._IDLE_FLUSH_TICKS: if idle_ticks >= self._IDLE_FLUSH_TICKS:
text = _strip_ansi( self._flush_partial_buf(buf)
buf.decode("utf-8", errors="replace").replace("\r", "")
)
if text:
self._write_output(text)
buf = b"" buf = b""
idle_ticks = 0 idle_ticks = 0
continue continue
@ -519,18 +535,10 @@ class RepoExplorer(tk.Tk):
if not chunk: if not chunk:
break break
buf += chunk buf += chunk
while b"\n" in buf: buf = self._process_complete_lines(buf)
line, buf = buf.split(b"\n", 1)
text = _strip_ansi(
line.decode("utf-8", errors="replace").replace("\r", "")
)
if text:
self._write_output(text + "\n")
# flush remainder # flush remainder
if buf: if buf:
text = _strip_ansi(buf.decode("utf-8", errors="replace").replace("\r", "")) self._flush_partial_buf(buf)
if text:
self._write_output(text)
if self._master_fd is not None: if self._master_fd is not None:
with contextlib.suppress(OSError): with contextlib.suppress(OSError):
os.close(self._master_fd) os.close(self._master_fd)

View File

@ -103,7 +103,7 @@ def _get_hltb_search_url() -> str:
if search_info and search_info.search_url: if search_info and search_info.search_url:
url: str = HTMLRequests.BASE_URL + search_info.search_url url: str = HTMLRequests.BASE_URL + search_info.search_url
return url return url
except Exception: # noqa: BLE001 except (OSError, RuntimeError, ValueError, TypeError):
logger.debug("Failed to discover HLTB search URL, using default") logger.debug("Failed to discover HLTB search URL, using default")
return "https://howlongtobeat.com/api/finder" return "https://howlongtobeat.com/api/finder"

View File

@ -44,7 +44,9 @@ def _get_shared_js_ws_url() -> str | None:
"""Query the CDP HTTP endpoint and return the SharedJSContext WS URL.""" """Query the CDP HTTP endpoint and return the SharedJSContext WS URL."""
url = f"http://127.0.0.1:{_CDP_PORT}/json" url = f"http://127.0.0.1:{_CDP_PORT}/json"
try: try:
with urllib.request.urlopen(url, timeout=5) as resp: # noqa: S310 if not url.startswith(("http://", "https://")):
return None
with urllib.request.urlopen(url, timeout=5) as resp:
targets = json.loads(resp.read()) targets = json.loads(resp.read())
except (OSError, ValueError): except (OSError, ValueError):
return None return None

View File

@ -135,7 +135,7 @@ def _ensure_steam_running() -> None:
# Check if any steam process is running (main client, not just helpers). # Check if any steam process is running (main client, not just helpers).
try: try:
result = subprocess.run( result = subprocess.run(
["pgrep", "-f", "steam.sh"], # noqa: S607 ["/usr/bin/pgrep", "-f", "steam.sh"],
capture_output=True, capture_output=True,
text=True, text=True,
check=False, check=False,
@ -937,7 +937,7 @@ def cmd_reset(config: Config, state: State) -> None:
count = unhide_all_games(owned) count = unhide_all_games(owned)
if count: if count:
_echo(f"Unhidden {count} games.") _echo(f"Unhidden {count} games.")
except Exception as exc: # noqa: BLE001 except (OSError, RuntimeError, ValueError) as exc:
_echo(f"Warning: could not unhide games: {exc}") _echo(f"Warning: could not unhide games: {exc}")
state.current_app_id = None state.current_app_id = None
@ -1024,7 +1024,7 @@ def _get_all_owned_app_ids(config: Config) -> list[int]:
client = SteamAPIClient(config.steam_api_key, config.steam_id) client = SteamAPIClient(config.steam_api_key, config.steam_id)
owned = client.get_owned_games() owned = client.get_owned_games()
return [g["appid"] for g in owned] return [g["appid"] for g in owned]
except Exception: # noqa: BLE001 except (OSError, RuntimeError, ValueError):
logger.warning("Could not fetch owned game list for hiding.") logger.warning("Could not fetch owned game list for hiding.")
return [] return []

View File

@ -25,6 +25,8 @@ PROTONDB_CACHE_FILE = CONFIG_DIR / "protondb_cache.json"
_PROTONDB_API = "https://www.protondb.com/api/v1/reports/summaries/{app_id}.json" _PROTONDB_API = "https://www.protondb.com/api/v1/reports/summaries/{app_id}.json"
MAX_CONCURRENT = 30 # parallel requests - be polite to the CDN MAX_CONCURRENT = 30 # parallel requests - be polite to the CDN
HTTP_NOT_FOUND = 404
# Tier ordering from best to worst. # Tier ordering from best to worst.
TIER_ORDER: dict[str, int] = { TIER_ORDER: dict[str, int] = {
"native": 0, "native": 0,
@ -101,7 +103,7 @@ async def _fetch_one(
async with sem: async with sem:
try: try:
async with session.get(url, timeout=aiohttp.ClientTimeout(total=15)) as r: async with session.get(url, timeout=aiohttp.ClientTimeout(total=15)) as r:
if r.status == 404: # noqa: PLR2004 if r.status == HTTP_NOT_FOUND:
return ProtonDBRating(app_id=app_id) return ProtonDBRating(app_id=app_id)
r.raise_for_status() r.raise_for_status()
data = await r.json(content_type=None) data = await r.json(content_type=None)
@ -113,7 +115,7 @@ async def _fetch_one(
confidence=data.get("confidence", ""), confidence=data.get("confidence", ""),
total_reports=data.get("total", 0), total_reports=data.get("total", 0),
) )
except Exception: # noqa: BLE001 except (aiohttp.ClientError, asyncio.TimeoutError, OSError):
logger.warning("ProtonDB fetch failed for AppID=%d", app_id) logger.warning("ProtonDB fetch failed for AppID=%d", app_id)
return ProtonDBRating(app_id=app_id) return ProtonDBRating(app_id=app_id)