style: fix ruff E721, E701, and E722 lint errors

This commit is contained in:
Andy
2026-02-16 13:37:23 -07:00
parent df92f9e4b6
commit 0217086abf
2 changed files with 135 additions and 104 deletions

View File

@@ -195,12 +195,7 @@ class dl:
sdh_suffix = ".sdh" if (subtitle.sdh or subtitle.cc) else "" sdh_suffix = ".sdh" if (subtitle.sdh or subtitle.cc) else ""
extension = (target_codec or subtitle.codec or Subtitle.Codec.SubRip).extension extension = (target_codec or subtitle.codec or Subtitle.Codec.SubRip).extension
if ( if not target_codec and not subtitle.codec and source_path and source_path.suffix:
not target_codec
and not subtitle.codec
and source_path
and source_path.suffix
):
extension = source_path.suffix.lstrip(".") extension = source_path.suffix.lstrip(".")
filename = f"{base_filename}.{lang_suffix}{forced_suffix}{sdh_suffix}.{extension}" filename = f"{base_filename}.{lang_suffix}{forced_suffix}{sdh_suffix}.{extension}"
@@ -1056,8 +1051,8 @@ class dl:
return return
# Enables manual selection for Series when --select-titles is set # Enables manual selection for Series when --select-titles is set
if select_titles and type(titles) == Series: if select_titles and isinstance(titles, Series):
console.print(Padding(Rule(f"[rule.text]Select Titles"), (1, 2))) console.print(Padding(Rule("[rule.text]Select Titles"), (1, 2)))
selection_titles = [] selection_titles = []
dependencies = {} dependencies = {}
@@ -1085,9 +1080,7 @@ class dl:
# Apply indentation only for multiple seasons # Apply indentation only for multiple seasons
prefix = " " if multiple_seasons else "" prefix = " " if multiple_seasons else ""
option_text = ( option_text = f"{prefix}{t.number}" + (f". {display_name}" if t.name else "")
f"{prefix}{t.number}" + (f". {display_name}" if t.name else "")
)
selection_titles.append(option_text) selection_titles.append(option_text)
current_ui_idx = len(selection_titles) - 1 current_ui_idx = len(selection_titles) - 1
@@ -1103,15 +1096,11 @@ class dl:
# Execute selector with dependencies (headers select all children) # Execute selector with dependencies (headers select all children)
selected_ui_idx = select_multiple( selected_ui_idx = select_multiple(
selection_titles, selection_titles, minimal_count=1, page_size=8, return_indices=True, dependencies=dependencies
minimal_count=1,
page_size=8,
return_indices=True,
dependencies=dependencies
) )
selection_end = time.time() selection_end = time.time()
start_time += (selection_end - selection_start) start_time += selection_end - selection_start
# Map UI indices back to title indices (excluding headers) # Map UI indices back to title indices (excluding headers)
selected_idx = [] selected_idx = []
@@ -1604,7 +1593,10 @@ class dl:
if audio_description: if audio_description:
standard_audio = [a for a in title.tracks.audio if not a.descriptive] standard_audio = [a for a in title.tracks.audio if not a.descriptive]
selected_standards = title.tracks.by_language( selected_standards = title.tracks.by_language(
standard_audio, processed_lang, per_language=per_language, exact_match=exact_lang standard_audio,
processed_lang,
per_language=per_language,
exact_match=exact_lang,
) )
desc_audio = [a for a in title.tracks.audio if a.descriptive] desc_audio = [a for a in title.tracks.audio if a.descriptive]
# Include all descriptive tracks for the requested languages. # Include all descriptive tracks for the requested languages.
@@ -1728,9 +1720,7 @@ class dl:
), ),
licence=partial( licence=partial(
service.get_playready_license service.get_playready_license
if ( if (is_playready_cdm(self.cdm))
is_playready_cdm(self.cdm)
)
and hasattr(service, "get_playready_license") and hasattr(service, "get_playready_license")
else service.get_widevine_license, else service.get_widevine_license,
title=title, title=title,
@@ -1848,9 +1838,7 @@ class dl:
# Subtitle output mode configuration (for sidecar originals) # Subtitle output mode configuration (for sidecar originals)
subtitle_output_mode = config.subtitle.get("output_mode", "mux") subtitle_output_mode = config.subtitle.get("output_mode", "mux")
sidecar_format = config.subtitle.get("sidecar_format", "srt") sidecar_format = config.subtitle.get("sidecar_format", "srt")
skip_subtitle_mux = ( skip_subtitle_mux = subtitle_output_mode == "sidecar" and (title.tracks.videos or title.tracks.audio)
subtitle_output_mode == "sidecar" and (title.tracks.videos or title.tracks.audio)
)
sidecar_subtitles: list[Subtitle] = [] sidecar_subtitles: list[Subtitle] = []
sidecar_original_paths: dict[str, Path] = {} sidecar_original_paths: dict[str, Path] = {}
if subtitle_output_mode in ("sidecar", "both") and not no_mux: if subtitle_output_mode in ("sidecar", "both") and not no_mux:
@@ -2101,7 +2089,9 @@ class dl:
sidecar_dir = config.directories.downloads sidecar_dir = config.directories.downloads
if not no_folder and isinstance(title, (Episode, Song)) and media_info: if not no_folder and isinstance(title, (Episode, Song)) and media_info:
sidecar_dir /= title.get_filename(media_info, show_service=not no_source, folder=True) sidecar_dir /= title.get_filename(
media_info, show_service=not no_source, folder=True
)
sidecar_dir.mkdir(parents=True, exist_ok=True) sidecar_dir.mkdir(parents=True, exist_ok=True)
with console.status("Saving subtitle sidecar files..."): with console.status("Saving subtitle sidecar files..."):

View File

@@ -1,21 +1,25 @@
import click
import sys import sys
import click
from rich.console import Group from rich.console import Group
from rich.live import Live from rich.live import Live
from rich.padding import Padding from rich.padding import Padding
from rich.table import Table from rich.table import Table
from rich.text import Text from rich.text import Text
from unshackle.core.console import console from unshackle.core.console import console
IS_WINDOWS = sys.platform == "win32" IS_WINDOWS = sys.platform == "win32"
if IS_WINDOWS: if IS_WINDOWS:
import msvcrt import msvcrt
class Selector: class Selector:
""" """
A custom interactive selector class using the Rich library. A custom interactive selector class using the Rich library.
Allows for multi-selection of items with pagination. Allows for multi-selection of items with pagination.
""" """
def __init__( def __init__(
self, self,
options: list[str], options: list[str],
@@ -24,7 +28,7 @@ class Selector:
page_size: int = 8, page_size: int = 8,
minimal_count: int = 0, minimal_count: int = 0,
dependencies: dict[int, list[int]] = None, dependencies: dict[int, list[int]] = None,
prefixes: list[str] = None prefixes: list[str] = None,
): ):
""" """
Initialize the Selector. Initialize the Selector.
@@ -61,8 +65,8 @@ class Selector:
if idx < len(self.options): if idx < len(self.options):
option = self.options[idx] option = self.options[idx]
is_cursor = (idx == self.cursor_index) is_cursor = idx == self.cursor_index
is_selected = (idx in self.selected_indices) is_selected = idx in self.selected_indices
symbol = "[X]" if is_selected else "[ ]" symbol = "[X]" if is_selected else "[ ]"
style = self.cursor_style if is_cursor else self.text_style style = self.cursor_style if is_cursor else self.text_style
@@ -80,7 +84,7 @@ class Selector:
info_text = Text( info_text = Text(
f"\n[Space]: Toggle [a]: All [←/→]: Page [Enter]: Confirm (Page {current_page}/{total_pages})", f"\n[Space]: Toggle [a]: All [←/→]: Page [Enter]: Confirm (Page {current_page}/{total_pages})",
style="gray" style="gray",
) )
return Padding(Group(table, info_text), (0, 5)) return Padding(Group(table, info_text), (0, 5))
@@ -144,28 +148,43 @@ class Selector:
Returns command strings like 'UP', 'DOWN', 'ENTER', etc. Returns command strings like 'UP', 'DOWN', 'ENTER', etc.
""" """
key = msvcrt.getch() key = msvcrt.getch()
if key == b'\x03' or key == b'\x1b': if key == b"\x03" or key == b"\x1b":
return 'CANCEL' return "CANCEL"
if key == b'\xe0' or key == b'\x00': if key == b"\xe0" or key == b"\x00":
try: try:
key = msvcrt.getch() key = msvcrt.getch()
if key == b'H': return 'UP' if key == b"H":
if key == b'P': return 'DOWN' return "UP"
if key == b'K': return 'LEFT' if key == b"P":
if key == b'M': return 'RIGHT' return "DOWN"
except: pass if key == b"K":
return "LEFT"
if key == b"M":
return "RIGHT"
except Exception:
pass
try: char = key.decode('utf-8', errors='ignore') try:
except: return None char = key.decode("utf-8", errors="ignore")
except Exception:
return None
if char in ('\r', '\n'): return 'ENTER' if char in ("\r", "\n"):
if char == ' ': return 'SPACE' return "ENTER"
if char in ('q', 'Q'): return 'QUIT' if char == " ":
if char in ('a', 'A'): return 'ALL' return "SPACE"
if char in ('w', 'W', 'k', 'K'): return 'UP' if char in ("q", "Q"):
if char in ('s', 'S', 'j', 'J'): return 'DOWN' return "QUIT"
if char in ('h', 'H'): return 'LEFT' if char in ("a", "A"):
if char in ('d', 'D', 'l', 'L'): return 'RIGHT' return "ALL"
if char in ("w", "W", "k", "K"):
return "UP"
if char in ("s", "S", "j", "J"):
return "DOWN"
if char in ("h", "H"):
return "LEFT"
if char in ("d", "D", "l", "L"):
return "RIGHT"
return None return None
def get_input_unix(self): def get_input_unix(self):
@@ -174,37 +193,49 @@ class Selector:
Returns command strings like 'UP', 'DOWN', 'ENTER', etc. Returns command strings like 'UP', 'DOWN', 'ENTER', etc.
""" """
char = click.getchar() char = click.getchar()
if char == '\x03': if char == "\x03":
return 'CANCEL' return "CANCEL"
mapping = { mapping = {
'\x1b[A': 'UP', "\x1b[A": "UP",
'\x1b[B': 'DOWN', "\x1b[B": "DOWN",
'\x1b[C': 'RIGHT', "\x1b[C": "RIGHT",
'\x1b[D': 'LEFT', "\x1b[D": "LEFT",
} }
if char in mapping: if char in mapping:
return mapping[char] return mapping[char]
if char == '\x1b': if char == "\x1b":
try: try:
next1 = click.getchar() next1 = click.getchar()
if next1 in ('[', 'O'): if next1 in ("[", "O"):
next2 = click.getchar() next2 = click.getchar()
if next2 == 'A': return 'UP' if next2 == "A":
if next2 == 'B': return 'DOWN' return "UP"
if next2 == 'C': return 'RIGHT' if next2 == "B":
if next2 == 'D': return 'LEFT' return "DOWN"
return 'CANCEL' if next2 == "C":
except: return "RIGHT"
return 'CANCEL' if next2 == "D":
return "LEFT"
return "CANCEL"
except Exception:
return "CANCEL"
if char in ('\r', '\n'): return 'ENTER' if char in ("\r", "\n"):
if char == ' ': return 'SPACE' return "ENTER"
if char in ('q', 'Q'): return 'QUIT' if char == " ":
if char in ('a', 'A'): return 'ALL' return "SPACE"
if char in ('w', 'W', 'k', 'K'): return 'UP' if char in ("q", "Q"):
if char in ('s', 'S', 'j', 'J'): return 'DOWN' return "QUIT"
if char in ('h', 'H'): return 'LEFT' if char in ("a", "A"):
if char in ('d', 'D', 'l', 'L'): return 'RIGHT' return "ALL"
if char in ("w", "W", "k", "K"):
return "UP"
if char in ("s", "S", "j", "J"):
return "DOWN"
if char in ("h", "H"):
return "LEFT"
if char in ("d", "D", "l", "L"):
return "RIGHT"
return None return None
def run(self) -> list[int]: def run(self) -> list[int]:
@@ -219,29 +250,39 @@ class Selector:
with Live(self.get_renderable(), console=console, auto_refresh=False, transient=True) as live: with Live(self.get_renderable(), console=console, auto_refresh=False, transient=True) as live:
while True: while True:
live.update(self.get_renderable(), refresh=True) live.update(self.get_renderable(), refresh=True)
if IS_WINDOWS: action = self.get_input_windows() if IS_WINDOWS:
else: action = self.get_input_unix() action = self.get_input_windows()
else:
action = self.get_input_unix()
if action == 'UP': self.move_cursor(-1) if action == "UP":
elif action == 'DOWN': self.move_cursor(1) self.move_cursor(-1)
elif action == 'LEFT': self.change_page(-1) elif action == "DOWN":
elif action == 'RIGHT': self.change_page(1) self.move_cursor(1)
elif action == 'SPACE': self.toggle_selection() elif action == "LEFT":
elif action == 'ALL': self.toggle_all() self.change_page(-1)
elif action in ('ENTER', 'QUIT'): elif action == "RIGHT":
self.change_page(1)
elif action == "SPACE":
self.toggle_selection()
elif action == "ALL":
self.toggle_all()
elif action in ("ENTER", "QUIT"):
if len(self.selected_indices) >= self.minimal_count: if len(self.selected_indices) >= self.minimal_count:
return sorted(list(self.selected_indices)) return sorted(list(self.selected_indices))
elif action == 'CANCEL': raise KeyboardInterrupt elif action == "CANCEL":
raise KeyboardInterrupt
except KeyboardInterrupt: except KeyboardInterrupt:
return [] return []
def select_multiple( def select_multiple(
options: list[str], options: list[str],
minimal_count: int = 1, minimal_count: int = 1,
page_size: int = 8, page_size: int = 8,
return_indices: bool = True, return_indices: bool = True,
cursor_style: str = "pink", cursor_style: str = "pink",
**kwargs **kwargs,
) -> list[int]: ) -> list[int]:
""" """
Drop-in replacement using custom Selector with global console. Drop-in replacement using custom Selector with global console.
@@ -259,7 +300,7 @@ def select_multiple(
text_style="text", text_style="text",
page_size=page_size, page_size=page_size,
minimal_count=minimal_count, minimal_count=minimal_count,
**kwargs **kwargs,
) )
selected_indices = selector.run() selected_indices = selector.run()