Closes #175: cached a bunch of calls that hit the database a lot from the DBus Manager
This commit is contained in:
6
Pipfile.lock
generated
6
Pipfile.lock
generated
@@ -157,10 +157,10 @@
|
||||
},
|
||||
"marshmallow": {
|
||||
"hashes": [
|
||||
"sha256:56663fa1d5385c14c6a1236badd166d6dee987a5f64d2b6cc099dadf96eb4f09",
|
||||
"sha256:f12203bf8d94c410ab4b8d66edfde4f8a364892bde1f6747179765559f93d62a"
|
||||
"sha256:c2673233aa21dde264b84349dc2fd1dce5f30ed724a0a00e75426734de5b84ab",
|
||||
"sha256:f88fe96434b1f0f476d54224d59333eba8ca1a203a2695683c1855675c4049a7"
|
||||
],
|
||||
"version": "==3.5.2"
|
||||
"version": "==3.6.0"
|
||||
},
|
||||
"marshmallow-enum": {
|
||||
"hashes": [
|
||||
|
@@ -8,7 +8,6 @@ from termcolor import cprint
|
||||
|
||||
todo_re = re.compile(r"\s*#\s*TODO:?\s*")
|
||||
accounted_for_todo = re.compile(r"\s*#\s*TODO:?\s*\((#\d+)\)")
|
||||
print_re = re.compile(r"\s+print\(.*\)")
|
||||
|
||||
|
||||
def noqa_re(error_id: str = ""):
|
||||
@@ -29,10 +28,6 @@ def check_file(path: Path) -> bool:
|
||||
eprint(f"{i}: {line}")
|
||||
valid = False
|
||||
|
||||
if print_re.search(line) and not noqa_re("T001").search(line):
|
||||
eprint(f"{i}: {line}")
|
||||
valid = False
|
||||
|
||||
file.close()
|
||||
return valid
|
||||
|
||||
|
14
setup.cfg
14
setup.cfg
@@ -1,8 +1,7 @@
|
||||
[flake8]
|
||||
select = C,E,F,W,B,B950
|
||||
ignore = E203, E402, E501, W503, ANN002, ANN003, ANN101, ANN102, ANN204
|
||||
extend-ignore = E203, E402, E722, W503, ANN002, ANN003, ANN101, ANN102, ANN204
|
||||
exclude = .git,__pycache__,build,dist,flatpak
|
||||
max-line-length = 80
|
||||
max-line-length = 88
|
||||
suppress-none-returning = True
|
||||
suppress-dummy-args = True
|
||||
application-import-names = sublime
|
||||
@@ -47,15 +46,6 @@ ignore_missing_imports = True
|
||||
[mypy-peewee]
|
||||
ignore_missing_imports = True
|
||||
|
||||
[yapf]
|
||||
based_on_style = pep8
|
||||
split_before_bitwise_operator = true
|
||||
split_before_arithmetic_operator = true
|
||||
split_before_dot = true
|
||||
split_before_logical_operator = true
|
||||
split_complex_comprehension = true
|
||||
split_before_first_argument = true
|
||||
|
||||
[tool:pytest]
|
||||
python_files = tests/**/*.py tests/*.py
|
||||
python_functions = test_* *_test
|
||||
|
@@ -383,6 +383,7 @@ class AdapterManager:
|
||||
def get_playlists(
|
||||
before_download: Callable[[], None] = lambda: None,
|
||||
force: bool = False, # TODO: rename to use_ground_truth_adapter?
|
||||
allow_download: bool = True,
|
||||
) -> Result[Sequence[Playlist]]:
|
||||
assert AdapterManager._instance
|
||||
partial_playlists_data = None
|
||||
@@ -396,6 +397,9 @@ class AdapterManager:
|
||||
except Exception:
|
||||
logging.exception(f'Error on {"get_playlists"} retrieving from cache.')
|
||||
|
||||
if not allow_download:
|
||||
raise CacheMissError(partial_data=partial_playlist_data)
|
||||
|
||||
if AdapterManager._instance.caching_adapter and force:
|
||||
AdapterManager._instance.caching_adapter.invalidate_data(
|
||||
CachingAdapter.CachedDataKey.PLAYLISTS, ()
|
||||
|
@@ -348,7 +348,7 @@ class SublimeMusicApp(Gtk.Application):
|
||||
self.on_song_clicked(
|
||||
None,
|
||||
song_idx,
|
||||
[s.id for s in playlist.songs],
|
||||
tuple(s.id for s in playlist.songs),
|
||||
{"active_playlist_id": playlist_id},
|
||||
)
|
||||
|
||||
@@ -598,7 +598,7 @@ class SublimeMusicApp(Gtk.Application):
|
||||
self.update_window()
|
||||
|
||||
@dbus_propagate()
|
||||
def on_play_next(self, action: Any, song_ids: List[str]):
|
||||
def on_play_next(self, action: Any, song_ids: Tuple[str, ...]):
|
||||
if self.app_config.state.current_song is None:
|
||||
insert_at = 0
|
||||
else:
|
||||
@@ -606,16 +606,18 @@ class SublimeMusicApp(Gtk.Application):
|
||||
|
||||
self.app_config.state.play_queue = (
|
||||
self.app_config.state.play_queue[:insert_at]
|
||||
+ list(song_ids)
|
||||
+ song_ids
|
||||
+ self.app_config.state.play_queue[insert_at:]
|
||||
)
|
||||
self.app_config.state.old_play_queue.extend(song_ids)
|
||||
self.app_config.state.old_play_queue += song_ids
|
||||
self.update_window()
|
||||
|
||||
@dbus_propagate()
|
||||
def on_add_to_queue(self, action: Any, song_ids: GLib.Variant):
|
||||
self.app_config.state.play_queue.extend(song_ids)
|
||||
self.app_config.state.old_play_queue.extend(song_ids)
|
||||
print(song_ids)
|
||||
print(type(song_ids))
|
||||
self.app_config.state.play_queue += tuple(song_ids)
|
||||
self.app_config.state.old_play_queue += tuple(song_ids)
|
||||
self.update_window()
|
||||
|
||||
def on_go_to_album(self, action: Any, album_id: GLib.Variant):
|
||||
@@ -714,12 +716,14 @@ class SublimeMusicApp(Gtk.Application):
|
||||
self,
|
||||
win: Any,
|
||||
song_index: int,
|
||||
song_queue: List[str],
|
||||
song_queue: Tuple[str, ...],
|
||||
metadata: Dict[str, Any],
|
||||
):
|
||||
print(type(song_queue), song_queue)
|
||||
song_queue = tuple(song_queue)
|
||||
# Reset the play queue so that we don't ever revert back to the
|
||||
# previous one.
|
||||
old_play_queue = song_queue.copy()
|
||||
old_play_queue = song_queue
|
||||
|
||||
if (force_shuffle := metadata.get("force_shuffle_state")) is not None:
|
||||
self.app_config.state.shuffle_on = force_shuffle
|
||||
@@ -729,10 +733,11 @@ class SublimeMusicApp(Gtk.Application):
|
||||
# If shuffle is enabled, then shuffle the playlist.
|
||||
if self.app_config.state.shuffle_on and not metadata.get("no_reshuffle"):
|
||||
song_id = song_queue[song_index]
|
||||
|
||||
del song_queue[song_index]
|
||||
random.shuffle(song_queue)
|
||||
song_queue = [song_id] + song_queue
|
||||
song_queue_list = list(
|
||||
song_queue[:song_index] + song_queue[song_index + 1 :]
|
||||
)
|
||||
random.shuffle(song_queue_list)
|
||||
song_queue = tuple(song_id, *song_queue_list)
|
||||
song_index = 0
|
||||
|
||||
self.play_song(
|
||||
@@ -743,11 +748,11 @@ class SublimeMusicApp(Gtk.Application):
|
||||
)
|
||||
|
||||
def on_songs_removed(self, win: Any, song_indexes_to_remove: List[int]):
|
||||
self.app_config.state.play_queue = [
|
||||
self.app_config.state.play_queue = tuple(
|
||||
song_id
|
||||
for i, song_id in enumerate(self.app_config.state.play_queue)
|
||||
if i not in song_indexes_to_remove
|
||||
]
|
||||
)
|
||||
|
||||
# Determine how many songs before the currently playing one were also
|
||||
# deleted.
|
||||
@@ -902,7 +907,7 @@ class SublimeMusicApp(Gtk.Application):
|
||||
|
||||
def do_update(f: Future):
|
||||
play_queue = f.result()
|
||||
new_play_queue = [s.id for s in play_queue.entry]
|
||||
new_play_queue = tuple(s.id for s in play_queue.entry)
|
||||
new_current_song_id = str(play_queue.current)
|
||||
new_song_progress = play_queue.position / 1000
|
||||
|
||||
@@ -965,8 +970,8 @@ class SublimeMusicApp(Gtk.Application):
|
||||
self,
|
||||
song_index: int,
|
||||
reset: bool = False,
|
||||
old_play_queue: List[str] = None,
|
||||
play_queue: List[str] = None,
|
||||
old_play_queue: Tuple[str, ...] = None,
|
||||
play_queue: Tuple[str, ...] = None,
|
||||
):
|
||||
# Do this the old fashioned way so that we can have access to ``reset``
|
||||
# in the callback.
|
||||
|
@@ -137,6 +137,7 @@ class AppConfiguration:
|
||||
return self._state
|
||||
|
||||
def load_state(self):
|
||||
self._state = UIState()
|
||||
if not self.server:
|
||||
return
|
||||
|
||||
|
@@ -170,27 +170,9 @@ class DBusManager:
|
||||
elif has_current_song:
|
||||
has_next_song = state.current_song_index < len(state.play_queue) - 1
|
||||
|
||||
active_playlist = (False, GLib.Variant("(oss)", ("/", "", "")))
|
||||
if state.active_playlist_id and AdapterManager.can_get_playlist_details():
|
||||
try:
|
||||
playlist = AdapterManager.get_playlist_details(
|
||||
state.active_playlist_id, allow_download=False
|
||||
).result()
|
||||
active_playlist = self.get_active_playlist(state.active_playlist_id)
|
||||
|
||||
cover_art = AdapterManager.get_cover_art_filename(
|
||||
playlist.cover_art, allow_download=False
|
||||
).result()
|
||||
|
||||
active_playlist = (
|
||||
True,
|
||||
GLib.Variant(
|
||||
"(oss)", ("/playlist/" + playlist.id, playlist.name, cover_art)
|
||||
),
|
||||
)
|
||||
except CacheMissError:
|
||||
pass
|
||||
|
||||
get_playlists_result = AdapterManager.get_playlists()
|
||||
get_playlists_result = AdapterManager.get_playlists(allow_download=False)
|
||||
if get_playlists_result.data_is_available:
|
||||
playlist_count = len(get_playlists_result.result())
|
||||
else:
|
||||
@@ -249,7 +231,38 @@ class DBusManager:
|
||||
},
|
||||
}
|
||||
|
||||
def get_mpris_metadata(self, idx: int, play_queue: List[str],) -> Dict[str, Any]:
|
||||
@functools.lru_cache(maxsize=10)
|
||||
def get_active_playlist(
|
||||
self, active_playlist_id: Optional[str]
|
||||
) -> Tuple[bool, GLib.Variant]:
|
||||
if not active_playlist_id or not AdapterManager.can_get_playlist_details():
|
||||
return (False, GLib.Variant("(oss)", ("/", "", "")))
|
||||
|
||||
try:
|
||||
playlist = AdapterManager.get_playlist_details(
|
||||
active_playlist_id, allow_download=False
|
||||
).result()
|
||||
|
||||
try:
|
||||
cover_art = AdapterManager.get_cover_art_filename(
|
||||
playlist.cover_art, allow_download=False
|
||||
).result()
|
||||
except CacheMissError:
|
||||
cover_art = ""
|
||||
|
||||
return (
|
||||
True,
|
||||
GLib.Variant(
|
||||
"(oss)", ("/playlist/" + playlist.id, playlist.name, cover_art)
|
||||
),
|
||||
)
|
||||
except CacheMissError:
|
||||
return (False, GLib.Variant("(oss)", ("/", "", "")))
|
||||
|
||||
@functools.lru_cache(maxsize=10)
|
||||
def get_mpris_metadata(
|
||||
self, idx: int, play_queue: Tuple[str, ...]
|
||||
) -> Dict[str, Any]:
|
||||
try:
|
||||
song = AdapterManager.get_song_details(
|
||||
play_queue[idx], allow_download=False
|
||||
@@ -283,7 +296,8 @@ class DBusManager:
|
||||
"xesam:title": song.title,
|
||||
}
|
||||
|
||||
def get_dbus_playlist(self, play_queue: List[str]) -> List[str]:
|
||||
@functools.lru_cache(maxsize=10)
|
||||
def get_dbus_playlist(self, play_queue: Tuple[str, ...]) -> List[str]:
|
||||
seen_counts: DefaultDict[str, int] = defaultdict(int)
|
||||
tracks = []
|
||||
for song_id in play_queue:
|
||||
|
@@ -2,7 +2,7 @@ import math
|
||||
|
||||
from datetime import datetime, timedelta
|
||||
from pathlib import Path
|
||||
from typing import Any, Callable, List, Optional
|
||||
from typing import Any, Callable, List, Optional, Tuple
|
||||
|
||||
import gi
|
||||
|
||||
@@ -46,7 +46,7 @@ class PlayerControls(Gtk.ActionBar):
|
||||
reordering_play_queue_song_list: bool = False
|
||||
current_song = None
|
||||
current_device = None
|
||||
current_play_queue: List[str] = []
|
||||
current_play_queue: Tuple[str, ...] = ()
|
||||
chromecasts: List[ChromecastPlayer] = []
|
||||
cover_art_update_order_token = 0
|
||||
play_queue_update_order_token = 0
|
||||
@@ -154,7 +154,6 @@ class PlayerControls(Gtk.ActionBar):
|
||||
self.update_device_list()
|
||||
|
||||
# Short circuit if no changes to the play queue
|
||||
print(self.current_play_queue, app_config.state.play_queue)
|
||||
if self.current_play_queue == app_config.state.play_queue:
|
||||
return
|
||||
self.current_play_queue = app_config.state.play_queue
|
||||
|
@@ -1,6 +1,6 @@
|
||||
from dataclasses import dataclass, field
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Optional
|
||||
from typing import Dict, Optional, Tuple
|
||||
|
||||
from sublime.adapters.api_objects import Song
|
||||
|
||||
@@ -36,8 +36,8 @@ class UIState:
|
||||
version: int = 1
|
||||
playing: bool = False
|
||||
current_song_index: int = -1
|
||||
play_queue: List[str] = field(default_factory=list)
|
||||
old_play_queue: List[str] = field(default_factory=list)
|
||||
play_queue: Tuple[str, ...] = field(default_factory=tuple)
|
||||
old_play_queue: Tuple[str, ...] = field(default_factory=tuple)
|
||||
_volume: Dict[str, float] = field(default_factory=lambda: {"this device": 100.0})
|
||||
is_muted: bool = False
|
||||
repeat_type: RepeatType = RepeatType.NO_REPEAT
|
||||
|
Reference in New Issue
Block a user