style: format all code to PEP8 (flake8 clean)
Reformat every module with autopep8 and hand-tune the remaining long lines so that `flake8` passes with default settings (max line length 79). No behavior changes: long f-strings, messages, QSS/Textual CSS rules and argument lists are only wrapped or split, an unused import and an unused local are dropped, and dbus-next D-Bus signature annotations carry targeted `# noqa` comments.
This commit is contained in:
178
tui.py
178
tui.py
@@ -149,9 +149,9 @@ class ListScreen(Screen):
|
||||
def row_selected(self, event: DataTable.RowSelected) -> None:
|
||||
track_id = str(event.row_key.value)
|
||||
index = next(
|
||||
(i for i, item in enumerate(self.tracks) if str(item.get("id")) == track_id),
|
||||
-1,
|
||||
)
|
||||
(i for i, item in enumerate(
|
||||
self.tracks) if str(
|
||||
item.get("id")) == track_id), -1, )
|
||||
if index >= 0:
|
||||
self.app.play_from_list(self.tracks, index, self.list_title)
|
||||
self.app.pop_screen()
|
||||
@@ -209,9 +209,8 @@ class FavoritesScreen(Screen):
|
||||
track_id = str(event.row_key.value)
|
||||
tracks = self.app.favorites
|
||||
index = next(
|
||||
(i for i, item in enumerate(tracks) if str(item.get("id")) == track_id),
|
||||
-1,
|
||||
)
|
||||
(i for i, item in enumerate(tracks) if str(
|
||||
item.get("id")) == track_id), -1, )
|
||||
if index >= 0:
|
||||
self.app.play_from_list(tracks, index, "Избранное")
|
||||
self.app.pop_screen()
|
||||
@@ -275,7 +274,8 @@ class SearchScreen(Screen):
|
||||
**{"page-size": 25},
|
||||
nocorrect="true",
|
||||
)
|
||||
tracks = (((payload.get("result") or {}).get("tracks") or {}).get("results")) or []
|
||||
tracks = (((payload.get("result") or {}).get(
|
||||
"tracks") or {}).get("results")) or []
|
||||
self.app.call_from_thread(self.fill, tracks)
|
||||
except SystemExit as exc:
|
||||
self.app.call_from_thread(self.failed, str(exc))
|
||||
@@ -297,9 +297,9 @@ class SearchScreen(Screen):
|
||||
def row_selected(self, event: DataTable.RowSelected) -> None:
|
||||
track_id = str(event.row_key.value)
|
||||
index = next(
|
||||
(i for i, item in enumerate(self.results) if str(item.get("id")) == track_id),
|
||||
-1,
|
||||
)
|
||||
(i for i, item in enumerate(
|
||||
self.results) if str(
|
||||
item.get("id")) == track_id), -1, )
|
||||
if index >= 0:
|
||||
self.app.play_from_list(self.results, index, "Поиск")
|
||||
self.app.pop_screen()
|
||||
@@ -391,14 +391,21 @@ class SettingsScreen(Screen):
|
||||
self.refresh_values()
|
||||
from settings import settings_path
|
||||
|
||||
self.query_one("#settings-path", Static).update(f"Файл: {settings_path()}")
|
||||
self.query_one(
|
||||
"#settings-path",
|
||||
Static).update(
|
||||
f"Файл: {
|
||||
settings_path()}")
|
||||
|
||||
def refresh_values(self) -> None:
|
||||
s = self.app.settings
|
||||
self.query_one("#vol-value", Static).update(f"{s['volume']} %")
|
||||
self.query_one("#seek-value", Static).update(f"{s['seek_step']} с")
|
||||
self.query_one("#autoplay-toggle", Button).label = "вкл" if s["autoplay"] else "выкл"
|
||||
self.query_one("#start-toggle", Button).label = START_QUEUE_LABELS[s["start_queue"]]
|
||||
self.query_one(
|
||||
"#autoplay-toggle",
|
||||
Button).label = "вкл" if s["autoplay"] else "выкл"
|
||||
self.query_one("#start-toggle",
|
||||
Button).label = START_QUEUE_LABELS[s["start_queue"]]
|
||||
self.query_one("#wave-toggle", Button).label = (
|
||||
"вкл" if s["wave_from_history"] else "выкл"
|
||||
)
|
||||
@@ -426,9 +433,12 @@ class SettingsScreen(Screen):
|
||||
elif bid == "start-toggle":
|
||||
order = list(START_QUEUES)
|
||||
index = order.index(s["start_queue"])
|
||||
self.app.update_setting("start_queue", order[(index + 1) % len(order)])
|
||||
self.app.update_setting(
|
||||
"start_queue", order[(index + 1) % len(order)])
|
||||
elif bid == "wave-toggle":
|
||||
self.app.update_setting("wave_from_history", not s["wave_from_history"])
|
||||
self.app.update_setting(
|
||||
"wave_from_history",
|
||||
not s["wave_from_history"])
|
||||
self.refresh_values()
|
||||
|
||||
|
||||
@@ -532,7 +542,10 @@ class MusicTui(App):
|
||||
}
|
||||
#menu { width: 5; min-width: 5; margin: 0 1 0 0; }
|
||||
#brand { text-style: bold; padding: 0 1; color: #f2f2f2; }
|
||||
#topstatus { width: 1fr; text-align: right; content-align: right middle; color: #8a8a8a; }
|
||||
#topstatus {
|
||||
width: 1fr; text-align: right; content-align: right middle;
|
||||
color: #8a8a8a;
|
||||
}
|
||||
|
||||
#phone {
|
||||
height: 1fr;
|
||||
@@ -548,7 +561,10 @@ class MusicTui(App):
|
||||
color: #8a8a8a;
|
||||
margin-bottom: 1;
|
||||
}
|
||||
#title { width: 100%; text-align: center; text-style: bold; color: #ffffff; }
|
||||
#title {
|
||||
width: 100%; text-align: center; text-style: bold;
|
||||
color: #ffffff;
|
||||
}
|
||||
#artist { width: 100%; text-align: center; color: #b0b0b0; }
|
||||
#album { width: 100%; text-align: center; color: #6a6a6a; }
|
||||
#time { width: 100%; text-align: center; color: #8a8a8a; margin-top: 1; }
|
||||
@@ -566,7 +582,10 @@ class MusicTui(App):
|
||||
background: #0a0a0a;
|
||||
}
|
||||
#back { width: 5; min-width: 5; margin-right: 1; }
|
||||
#screen-title { text-style: bold; width: 1fr; content-align: left middle; color: #f2f2f2; }
|
||||
#screen-title {
|
||||
text-style: bold; width: 1fr; content-align: left middle;
|
||||
color: #f2f2f2;
|
||||
}
|
||||
#screen-status { height: 1; padding: 0 1; color: #8a8a8a; }
|
||||
#list-table { height: 1fr; background: #000000; }
|
||||
#search-row { height: 3; padding: 0 1; }
|
||||
@@ -618,7 +637,10 @@ class MusicTui(App):
|
||||
self.settings = load_settings()
|
||||
self.api: Api | None = None
|
||||
self.uid = ""
|
||||
self.player = MusicPlayer(player, volume=int(self.settings.get("volume", 80)))
|
||||
self.player = MusicPlayer(
|
||||
player, volume=int(
|
||||
self.settings.get(
|
||||
"volume", 80)))
|
||||
self.wave: list[dict] = []
|
||||
self.favorites: list[dict] = []
|
||||
self.liked_ids: set[str] = set()
|
||||
@@ -648,7 +670,12 @@ class MusicTui(App):
|
||||
yield Static("", id="artist")
|
||||
yield Static("", id="album")
|
||||
yield Static("0:00 / 0:00", id="time")
|
||||
yield ProgressBar(total=100, show_eta=False, show_percentage=False, id="progress")
|
||||
yield ProgressBar(
|
||||
total=100,
|
||||
show_eta=False,
|
||||
show_percentage=False,
|
||||
id="progress",
|
||||
)
|
||||
with Horizontal(id="controls"):
|
||||
yield Button("⏮", id="prev")
|
||||
yield Button("▶", id="playpause")
|
||||
@@ -671,7 +698,10 @@ class MusicTui(App):
|
||||
self.exit()
|
||||
return
|
||||
if not self.api.token:
|
||||
self.notify("Сначала войди: python mtsmusic.py login", severity="error", timeout=8)
|
||||
self.notify(
|
||||
"Сначала войди: python mtsmusic.py login",
|
||||
severity="error",
|
||||
timeout=8)
|
||||
self.set_timer(3, self.exit)
|
||||
return
|
||||
self.load_initial()
|
||||
@@ -690,7 +720,8 @@ class MusicTui(App):
|
||||
return value - (value % 2)
|
||||
|
||||
def apply_cover_width(self) -> None:
|
||||
self.cover_width = self.cover_width_for(self.size.width, self.size.height)
|
||||
self.cover_width = self.cover_width_for(
|
||||
self.size.width, self.size.height)
|
||||
self.apply_column_width(self.cover_width)
|
||||
|
||||
def apply_column_width(self, width: int) -> None:
|
||||
@@ -751,15 +782,22 @@ class MusicTui(App):
|
||||
liked = {str(track.get("id")) for track in start}
|
||||
else:
|
||||
payload = api.get(f"/users/{self.uid}/likes/tracks")
|
||||
refs = ((payload.get("result") or {}).get("library") or {}).get("tracks") or []
|
||||
refs = ((payload.get("result") or {}).get(
|
||||
"library") or {}).get("tracks") or []
|
||||
liked = {str(ref.get("id")) for ref in refs}
|
||||
if want == "history":
|
||||
start, name = list(self.history), "История"
|
||||
self.call_from_thread(self.apply_initial, wave, liked, start, name)
|
||||
except SystemExit as exc:
|
||||
self.call_from_thread(self.notify, f"Ошибка загрузки: {exc}", severity="error")
|
||||
self.call_from_thread(
|
||||
self.notify,
|
||||
f"Ошибка загрузки: {exc}",
|
||||
severity="error")
|
||||
except requests.RequestException as exc:
|
||||
self.call_from_thread(self.notify, f"Сеть недоступна: {exc}", severity="error")
|
||||
self.call_from_thread(
|
||||
self.notify,
|
||||
f"Сеть недоступна: {exc}",
|
||||
severity="error")
|
||||
|
||||
def apply_initial(
|
||||
self,
|
||||
@@ -795,7 +833,10 @@ class MusicTui(App):
|
||||
track_id = str(track.get("id"))
|
||||
liked = track_id in self.liked_ids
|
||||
|
||||
self.query_one("#title", Static).update(Text(track.get("title") or "?"))
|
||||
self.query_one(
|
||||
"#title", Static).update(
|
||||
Text(
|
||||
track.get("title") or "?"))
|
||||
self.query_one("#artist", Static).update(Text(track_artist(track)))
|
||||
self.query_one("#album", Static).update(Text(track_album(track)))
|
||||
self.update_like_button(liked)
|
||||
@@ -806,19 +847,26 @@ class MusicTui(App):
|
||||
|
||||
def update_like_button(self, liked: bool | None = None) -> None:
|
||||
if liked is None:
|
||||
liked = bool(self.current and str(self.current.get("id")) in self.liked_ids)
|
||||
liked = bool(
|
||||
self.current and str(
|
||||
self.current.get("id")) in self.liked_ids)
|
||||
button = self.query_one("#like", Button)
|
||||
heart = "♥" if liked else "♡"
|
||||
suffix = " Избранное" if self.cover_width >= 34 else ""
|
||||
button.label = heart + suffix
|
||||
|
||||
def update_play_button(self) -> None:
|
||||
self.query_one("#playpause", Button).label = "⏸" if self.player.paused else "▶"
|
||||
self.query_one(
|
||||
"#playpause",
|
||||
Button).label = "⏸" if self.player.paused else "▶"
|
||||
self._update_mpris_status()
|
||||
|
||||
def update_time(self) -> None:
|
||||
duration = (self.current or {}).get("durationMs") or 0
|
||||
elapsed = min(self.player.elapsed(), duration / 1000 if duration else 0)
|
||||
elapsed = min(
|
||||
self.player.elapsed(),
|
||||
duration /
|
||||
1000 if duration else 0)
|
||||
bar = self.query_one("#progress", ProgressBar)
|
||||
bar.update(total=max(duration / 1000, 1), progress=elapsed)
|
||||
self.query_one("#time", Static).update(
|
||||
@@ -867,7 +915,9 @@ class MusicTui(App):
|
||||
def fetch_cover(self, token: int, url: str) -> None:
|
||||
try:
|
||||
force_ipv4()
|
||||
response = requests.get(url, headers={"User-Agent": USER_AGENT}, timeout=20)
|
||||
response = requests.get(
|
||||
url, headers={
|
||||
"User-Agent": USER_AGENT}, timeout=20)
|
||||
response.raise_for_status()
|
||||
data = response.content
|
||||
except (requests.RequestException, OSError):
|
||||
@@ -884,7 +934,11 @@ class MusicTui(App):
|
||||
|
||||
# -- воспроизведение --------------------------------------------------
|
||||
|
||||
def play_from_list(self, tracks: list[dict], index: int, name: str) -> None:
|
||||
def play_from_list(
|
||||
self,
|
||||
tracks: list[dict],
|
||||
index: int,
|
||||
name: str) -> None:
|
||||
if not (0 <= index < len(tracks)):
|
||||
return
|
||||
self.queue_name = name
|
||||
@@ -927,14 +981,20 @@ class MusicTui(App):
|
||||
url, item = resolve_stream(api, str(track.get("id")))
|
||||
except SystemExit as exc:
|
||||
self.call_from_thread(
|
||||
self.notify, f"Не удалось открыть трек: {exc}", severity="error"
|
||||
)
|
||||
self.notify,
|
||||
f"Не удалось открыть трек: {exc}",
|
||||
severity="error")
|
||||
return
|
||||
self.call_from_thread(
|
||||
self.start_playback, token, track, url, bool(item.get("preview"))
|
||||
)
|
||||
|
||||
def start_playback(self, token: int, track: dict, url: str, preview: bool) -> None:
|
||||
def start_playback(
|
||||
self,
|
||||
token: int,
|
||||
track: dict,
|
||||
url: str,
|
||||
preview: bool) -> None:
|
||||
if token != self.play_token:
|
||||
return
|
||||
self.run_worker(self._play_url(track, url, preview), group="playback")
|
||||
@@ -962,7 +1022,10 @@ class MusicTui(App):
|
||||
|
||||
def action_play_current(self) -> None:
|
||||
if self.current:
|
||||
self.play_track(self.current, self.queue or self.wave, self.current_index)
|
||||
self.play_track(
|
||||
self.current,
|
||||
self.queue or self.wave,
|
||||
self.current_index)
|
||||
|
||||
def try_next(self, direction: int) -> None:
|
||||
queue = self.queue or self.wave
|
||||
@@ -995,7 +1058,12 @@ class MusicTui(App):
|
||||
if not self.current or not self.player.is_playing():
|
||||
return
|
||||
duration = (self.current.get("durationMs") or 0) / 1000
|
||||
self.run_worker(self._seek(delta, duration), group="seek", exclusive=True)
|
||||
self.run_worker(
|
||||
self._seek(
|
||||
delta,
|
||||
duration),
|
||||
group="seek",
|
||||
exclusive=True)
|
||||
|
||||
async def _seek(self, delta: float, duration: float) -> None:
|
||||
await self.player.seek(delta, duration)
|
||||
@@ -1035,19 +1103,29 @@ class MusicTui(App):
|
||||
]
|
||||
self.call_from_thread(self.apply_more_wave, tracks, then_play)
|
||||
except SystemExit as exc:
|
||||
self.call_from_thread(self.notify, f"Ошибка волны: {exc}", severity="error")
|
||||
self.call_from_thread(
|
||||
self.notify,
|
||||
f"Ошибка волны: {exc}",
|
||||
severity="error")
|
||||
|
||||
def apply_more_wave(self, tracks: list[dict], then_play: int | None) -> None:
|
||||
def apply_more_wave(
|
||||
self,
|
||||
tracks: list[dict],
|
||||
then_play: int | None) -> None:
|
||||
known = {str(track.get("id")) for track in self.wave}
|
||||
added = [track for track in tracks if str(track.get("id")) not in known]
|
||||
added = [
|
||||
track for track in tracks if str(
|
||||
track.get("id")) not in known]
|
||||
self.wave.extend(added)
|
||||
self.set_topstatus(f"Волна · {len(self.wave)} · ♥ {len(self.liked_ids)}")
|
||||
self.set_topstatus(
|
||||
f"Волна · {len(self.wave)} · ♥ {len(self.liked_ids)}")
|
||||
if then_play is not None and then_play < len(self.queue):
|
||||
self.play_track(self.queue[then_play], self.queue, then_play)
|
||||
elif then_play is not None and added:
|
||||
self.queue = self.wave
|
||||
self.current_index = len(self.wave) - len(added)
|
||||
self.play_track(self.wave[self.current_index], self.wave, self.current_index)
|
||||
self.play_track(self.wave[self.current_index],
|
||||
self.wave, self.current_index)
|
||||
|
||||
# -- избранное --------------------------------------------------------
|
||||
|
||||
@@ -1064,7 +1142,10 @@ class MusicTui(App):
|
||||
albums = track.get("albums") or []
|
||||
album = str(albums[0].get("id")) if albums else ""
|
||||
if not album:
|
||||
self.call_from_thread(self.notify, "У трека нет альбома", severity="error")
|
||||
self.call_from_thread(
|
||||
self.notify,
|
||||
"У трека нет альбома",
|
||||
severity="error")
|
||||
return
|
||||
liked = track_id in self.liked_ids
|
||||
try:
|
||||
@@ -1079,7 +1160,10 @@ class MusicTui(App):
|
||||
**{"track-id": f"{track_id}:{album}"},
|
||||
)
|
||||
except SystemExit as exc:
|
||||
self.call_from_thread(self.notify, f"Ошибка избранного: {exc}", severity="error")
|
||||
self.call_from_thread(
|
||||
self.notify,
|
||||
f"Ошибка избранного: {exc}",
|
||||
severity="error")
|
||||
return
|
||||
self.call_from_thread(self.apply_like, track, not liked)
|
||||
|
||||
@@ -1124,7 +1208,10 @@ class MusicTui(App):
|
||||
def apply_settings(self) -> None:
|
||||
volume = int(self.settings.get("volume", 80))
|
||||
if self.player.volume != volume:
|
||||
self.run_worker(self.player.set_volume(volume), group="volume", exclusive=True)
|
||||
self.run_worker(
|
||||
self.player.set_volume(volume),
|
||||
group="volume",
|
||||
exclusive=True)
|
||||
if self.mpris:
|
||||
self.mpris.update_volume(volume / 100)
|
||||
|
||||
@@ -1194,7 +1281,8 @@ class MusicTui(App):
|
||||
self.seek(target - self.player.elapsed())
|
||||
|
||||
def mpris_set_volume(self, value: float) -> None:
|
||||
self.update_setting("volume", int(round(max(0.0, min(1.0, value)) * 100)))
|
||||
self.update_setting("volume", int(
|
||||
round(max(0.0, min(1.0, value)) * 100)))
|
||||
|
||||
def action_show_favorites(self) -> None:
|
||||
self.push_screen(FavoritesScreen())
|
||||
|
||||
Reference in New Issue
Block a user