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