Got things to a good state that can be built off of

This commit is contained in:
Sumner Evans
2020-04-17 20:33:41 -06:00
parent 0cfe31283d
commit fdb02a7e76
13 changed files with 258 additions and 55 deletions

View File

@@ -11,7 +11,7 @@ flake8-comprehensions = "*"
flake8-pep3101 = "*"
flake8-print = "*"
graphviz = "*"
jedi = "*"
jedi = "<0.16"
lxml = "*"
mypy = "*"
pytest = "*"
@@ -19,7 +19,6 @@ pytest-cov = "*"
rope = "*"
rst2html5 = "*"
sphinx = "*"
sphinx-autodoc-typehints = "*"
sphinx-rtd-theme = "*"
termcolor = "*"
yapf = "*"

16
Pipfile.lock generated
View File

@@ -1,7 +1,7 @@
{
"_meta": {
"hash": {
"sha256": "1f998ec38046cff69f63ed51610a1ca33bef37635020695781f57684daa9da01"
"sha256": "ec62e729c70d9ce38576ae97cfdd88b0a006886cbca1fa4ff0160383e96453a6"
},
"pipfile-spec": 6,
"requires": {
@@ -447,11 +447,11 @@
},
"jedi": {
"hashes": [
"sha256:cd60c93b71944d628ccac47df9a60fec53150de53d42dc10a7fc4b5ba6aae798",
"sha256:df40c97641cb943661d2db4c33c2e1ff75d491189423249e989bcea4464f3030"
"sha256:1349c1e8c107095a55386628bb3b2a79422f3a2cab8381e34ce19909e0cf5064",
"sha256:e909527104a903606dd63bea6e8e888833f0ef087057829b89a18364a856f807"
],
"index": "pypi",
"version": "==0.17.0"
"version": "==0.15.2"
},
"jinja2": {
"hashes": [
@@ -694,14 +694,6 @@
"index": "pypi",
"version": "==3.0.3"
},
"sphinx-autodoc-typehints": {
"hashes": [
"sha256:27c9e6ef4f4451766ab8d08b2d8520933b97beb21c913f3df9ab2e59b56e6c6c",
"sha256:a6b3180167479aca2c4d1ed3b5cb044a70a76cccd6b38662d39288ebd9f0dff0"
],
"index": "pypi",
"version": "==1.10.3"
},
"sphinx-rtd-theme": {
"hashes": [
"sha256:00cf895504a7895ee433807c62094cf1e95f065843bf3acd17037c3e9a2becd4",

View File

@@ -286,6 +286,13 @@ def generate_class_for_type(type_name: str) -> str:
indent_str = ' {}'
if not has_properties:
code.append(indent_str.format('pass'))
else:
code.append('')
code.append(
indent_str.format(
'def get(self, key: str, default: Any = None) -> Any:'))
code.append(
indent_str.format(' return getattr(self, key, default)'))
return '\n'.join(code)
@@ -304,7 +311,7 @@ with open(output_file, 'w+') as outfile:
'from dataclasses import dataclass, field',
'from datetime import datetime',
'from enum import Enum',
'from typing import List, Optional',
'from typing import Any, List, Optional',
'',
'from sublime.server.api_object import APIObject',
*map(generate_class_for_type, output_order),

View File

@@ -34,7 +34,7 @@ release = f'v{sublime.__version__}'
# ones.
extensions = [
'sphinx.ext.autodoc',
'sphinx_autodoc_typehints',
'sphinx.ext.autosectionlabel',
'sphinx.ext.intersphinx',
'sphinx.ext.mathjax',
'sphinx.ext.viewcode',
@@ -46,6 +46,10 @@ autodoc_default_options = {
'show-inheritance': True,
'special-members': '__init__',
}
autosectionlabel_prefix_document = True
intersphinx_mapping = {
'python': ('https://docs.python.org/3', None),
}
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']

View File

@@ -2,6 +2,7 @@
ignore = E402, W503, ANN002, ANN003, ANN101, ANN102, ANN204
exclude = .git,__pycache__,build,dist,flatpak
suppress-none-returning = True
suppress-dummy-args = True
application-import-names = sublime
import-order-style = edited

View File

@@ -451,7 +451,7 @@ class SublimeMusicApp(Gtk.Application):
@dbus_propagate()
def on_refresh_window(
self,
_: Any,
_,
state_updates: Dict[str, Any],
force: bool = False,
):
@@ -686,7 +686,7 @@ class SublimeMusicApp(Gtk.Application):
# Update the window according to the new server configuration.
self.update_window()
def on_stack_change(self, stack: Gtk.Stack, _: Any):
def on_stack_change(self, stack: Gtk.Stack, _):
self.app_config.state.current_tab = stack.get_visible_child_name()
self.update_window()
@@ -815,7 +815,7 @@ class SublimeMusicApp(Gtk.Application):
self.update_window()
@dbus_propagate()
def on_volume_change(self, _: Any, value: float):
def on_volume_change(self, _, value: float):
self.app_config.state.volume = value
self.player.volume = self.app_config.state.volume
self.update_window()

View File

@@ -368,7 +368,8 @@ class CacheManager(metaclass=Singleton):
meta_json = json.load(f)
except json.decoder.JSONDecodeError:
# Just continue with the default meta_json.
pass
logging.warning(
'Unable to load cache', stack_info=True)
cache_version = meta_json.get('version', 0)
@@ -411,7 +412,6 @@ class CacheManager(metaclass=Singleton):
('artist_details', ArtistWithAlbumsID3, dict),
('artist_infos', ArtistInfo2, dict),
]
return
for name, type_name, default in cache_configs:
if default == list:
self.cache[name] = [

View File

@@ -33,11 +33,15 @@ def from_json(template_type: Any, data: Any) -> Any:
instance = None
# Handle generics. List[*], Dict[*, *] in particular.
elif type(template_type) == typing._GenericAlias: # type: ignore
if getattr(template_type, '__origin__') == typing.Union:
template_type = template_type.__args__[0]
instance = from_json(template_type, data)
else:
# Having to use this because things changed in Python 3.7.
class_name = template_type._name
# This is not very elegant since it doesn't allow things which sublass
# from List or Dict. For my purposes, this doesn't matter.
# This is not very elegant since it doesn't allow things which
# sublass from List or Dict. For my purposes, this doesn't matter.
if class_name == 'List':
inner_type = template_type.__args__[0]
instance = [from_json(inner_type, value) for value in data]
@@ -72,9 +76,13 @@ def from_json(template_type: Any, data: Any) -> Any:
# Handle everything else by first instantiating the class, then adding
# all of the sub-elements, recursively calling from_json on them.
else:
instance = template_type()
for field, field_type in annotations.items():
value = data.get(field)
setattr(instance, field, from_json(field_type, value))
# for field, field_type in annotations.items():
# value = data.get(field)
# setattr(instance, field, from_json(field_type, value))
instance = template_type(
**{
field: from_json(field_type, data.get(field))
for field, field_type in annotations.items()
})
return instance

View File

@@ -1,6 +1,8 @@
from dataclasses import Field, fields
# from dataclasses import Field, fields
from typing import Any, Dict
from sublime.from_json import from_json as _from_json
class APIObject:
"""Defines the base class for objects coming from the Subsonic API."""
@@ -15,11 +17,4 @@ class APIObject:
:param data: a Python dictionary representation of the data to
deserialize
"""
if data is None:
return data
print('=' * 80)
deserialized = cls.__call__(**data)
for field in fields(cls):
print(field)
value = getattr(deserialized, field.name)
print('ohea', value)
return _from_json(cls, data)

View File

@@ -8,7 +8,7 @@ script or run it on a new API version.
from dataclasses import dataclass, field
from datetime import datetime
from enum import Enum
from typing import List, Optional
from typing import Any, List, Optional
from sublime.server.api_object import APIObject
@@ -23,6 +23,9 @@ class AlbumInfo(APIObject):
largeImageUrl: List[str] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class AverageRating(APIObject, float):
@@ -35,6 +38,9 @@ class MediaType(APIObject, Enum):
AUDIOBOOK = 'audiobook'
VIDEO = 'video'
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class UserRating(APIObject, int):
@@ -76,12 +82,18 @@ class Child(APIObject):
originalWidth: Optional[int] = None
originalHeight: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class AlbumList(APIObject):
album: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class AlbumID3(APIObject):
@@ -99,12 +111,18 @@ class AlbumID3(APIObject):
year: Optional[int] = None
genre: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class AlbumList2(APIObject):
album: List[AlbumID3] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class AlbumWithSongsID3(APIObject):
@@ -123,6 +141,9 @@ class AlbumWithSongsID3(APIObject):
year: Optional[int] = None
genre: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Artist(APIObject):
@@ -134,6 +155,9 @@ class Artist(APIObject):
userRating: Optional[UserRating] = None
averageRating: Optional[AverageRating] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ArtistInfoBase(APIObject):
@@ -145,6 +169,9 @@ class ArtistInfoBase(APIObject):
largeImageUrl: List[str] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ArtistInfo(APIObject):
@@ -157,6 +184,9 @@ class ArtistInfo(APIObject):
mediumImageUrl: List[str] = field(default_factory=list)
largeImageUrl: List[str] = field(default_factory=list)
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ArtistID3(APIObject):
@@ -168,6 +198,9 @@ class ArtistID3(APIObject):
artistImageUrl: Optional[str] = None
starred: Optional[datetime] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ArtistInfo2(APIObject):
@@ -180,6 +213,9 @@ class ArtistInfo2(APIObject):
mediumImageUrl: List[str] = field(default_factory=list)
largeImageUrl: List[str] = field(default_factory=list)
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ArtistWithAlbumsID3(APIObject):
@@ -192,6 +228,9 @@ class ArtistWithAlbumsID3(APIObject):
artistImageUrl: Optional[str] = None
starred: Optional[datetime] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class IndexID3(APIObject):
@@ -199,6 +238,9 @@ class IndexID3(APIObject):
artist: List[ArtistID3] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ArtistsID3(APIObject):
@@ -206,6 +248,9 @@ class ArtistsID3(APIObject):
index: List[IndexID3] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Bookmark(APIObject):
@@ -217,12 +262,18 @@ class Bookmark(APIObject):
value: Optional[str] = None
comment: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Bookmarks(APIObject):
bookmark: List[Bookmark] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ChatMessage(APIObject):
@@ -231,12 +282,18 @@ class ChatMessage(APIObject):
message: str
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ChatMessages(APIObject):
chatMessage: List[ChatMessage] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Directory(APIObject):
@@ -250,6 +307,9 @@ class Directory(APIObject):
averageRating: Optional[AverageRating] = None
playCount: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Error(APIObject):
@@ -257,6 +317,9 @@ class Error(APIObject):
value: Optional[str] = None
message: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Genre(APIObject):
@@ -264,12 +327,18 @@ class Genre(APIObject):
albumCount: int
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Genres(APIObject):
genre: List[Genre] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Index(APIObject):
@@ -277,6 +346,9 @@ class Index(APIObject):
artist: List[Artist] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Indexes(APIObject):
@@ -287,6 +359,9 @@ class Indexes(APIObject):
child: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class InternetRadioStation(APIObject):
@@ -296,12 +371,18 @@ class InternetRadioStation(APIObject):
value: Optional[str] = None
homePageUrl: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class InternetRadioStations(APIObject):
internetRadioStation: List[InternetRadioStation] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class JukeboxStatus(APIObject):
@@ -311,6 +392,9 @@ class JukeboxStatus(APIObject):
value: Optional[str] = None
position: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class JukeboxPlaylist(APIObject):
@@ -321,6 +405,9 @@ class JukeboxPlaylist(APIObject):
value: Optional[str] = None
position: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class License(APIObject):
@@ -330,6 +417,9 @@ class License(APIObject):
licenseExpires: Optional[datetime] = None
trialExpires: Optional[datetime] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Lyrics(APIObject):
@@ -337,6 +427,9 @@ class Lyrics(APIObject):
value: Optional[str] = None
title: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class MusicFolder(APIObject):
@@ -344,12 +437,18 @@ class MusicFolder(APIObject):
value: Optional[str] = None
name: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class MusicFolders(APIObject):
musicFolder: List[MusicFolder] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
class PodcastStatus(APIObject, Enum):
NEW = 'new'
@@ -359,6 +458,9 @@ class PodcastStatus(APIObject, Enum):
DELETED = 'deleted'
SKIPPED = 'skipped'
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class PodcastEpisode(APIObject):
@@ -400,12 +502,18 @@ class PodcastEpisode(APIObject):
originalWidth: Optional[int] = None
originalHeight: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class NewestPodcasts(APIObject):
episode: List[PodcastEpisode] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class NowPlayingEntry(APIObject):
@@ -446,12 +554,18 @@ class NowPlayingEntry(APIObject):
originalWidth: Optional[int] = None
originalHeight: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class NowPlaying(APIObject):
entry: List[NowPlayingEntry] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class PlayQueue(APIObject):
@@ -463,6 +577,9 @@ class PlayQueue(APIObject):
current: Optional[int] = None
position: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Playlist(APIObject):
@@ -479,6 +596,9 @@ class Playlist(APIObject):
public: Optional[bool] = None
coverArt: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class PlaylistWithSongs(APIObject):
@@ -496,12 +616,18 @@ class PlaylistWithSongs(APIObject):
public: Optional[bool] = None
coverArt: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Playlists(APIObject):
playlist: List[Playlist] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class PodcastChannel(APIObject):
@@ -516,17 +642,26 @@ class PodcastChannel(APIObject):
originalImageUrl: Optional[str] = None
errorMessage: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Podcasts(APIObject):
channel: List[PodcastChannel] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
class ResponseStatus(APIObject, Enum):
OK = 'ok'
FAILED = 'failed'
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class ScanStatus(APIObject):
@@ -534,6 +669,9 @@ class ScanStatus(APIObject):
value: Optional[str] = None
count: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class SearchResult(APIObject):
@@ -542,6 +680,9 @@ class SearchResult(APIObject):
match: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class SearchResult2(APIObject):
@@ -550,6 +691,9 @@ class SearchResult2(APIObject):
song: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class SearchResult3(APIObject):
@@ -558,6 +702,9 @@ class SearchResult3(APIObject):
song: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Share(APIObject):
@@ -572,30 +719,45 @@ class Share(APIObject):
expires: Optional[datetime] = None
lastVisited: Optional[datetime] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Shares(APIObject):
share: List[Share] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class SimilarSongs(APIObject):
song: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class SimilarSongs2(APIObject):
song: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Songs(APIObject):
song: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Starred(APIObject):
@@ -604,6 +766,9 @@ class Starred(APIObject):
song: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Starred2(APIObject):
@@ -612,12 +777,18 @@ class Starred2(APIObject):
song: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class TopSongs(APIObject):
song: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class User(APIObject):
@@ -641,12 +812,18 @@ class User(APIObject):
maxBitRate: Optional[int] = None
avatarLastChanged: Optional[datetime] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Users(APIObject):
user: List[User] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Version(APIObject, str):
@@ -660,6 +837,9 @@ class AudioTrack(APIObject):
name: Optional[str] = None
languageCode: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Captions(APIObject):
@@ -667,6 +847,9 @@ class Captions(APIObject):
value: Optional[str] = None
name: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class VideoConversion(APIObject):
@@ -675,6 +858,9 @@ class VideoConversion(APIObject):
bitRate: Optional[int] = None
audioTrackId: Optional[int] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class VideoInfo(APIObject):
@@ -684,12 +870,18 @@ class VideoInfo(APIObject):
conversion: List[VideoConversion] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Videos(APIObject):
video: List[Child] = field(default_factory=list)
value: Optional[str] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)
@dataclass(frozen=True)
class Response(APIObject):
@@ -739,3 +931,6 @@ class Response(APIObject):
value: Optional[str] = None
status: Optional[ResponseStatus] = None
version: Optional[Version] = None
def get(self, key: str, default: Any = None) -> Any:
return getattr(self, key, default)

View File

@@ -148,8 +148,7 @@ class Server:
)
raise Exception(f'Subsonic API Error #{code}: {message}')
print(subsonic_response)
response = Response.from_dict(subsonic_response)
response = Response.from_json(subsonic_response)
# Check for an error and if it exists, raise it.
if response.error:

View File

@@ -66,6 +66,7 @@ class UIState:
@property
def current_song(self) -> Optional[Child]:
from sublime.cache_manager import CacheManager
if (not self.play_queue or self.current_song_index < 0
or not CacheManager.ready()):
return None

View File

@@ -2,10 +2,12 @@ import pytest
from sublime.adapters import Adapter, AdapterManager
def test_adapter_manager_singleton():
AdapterManager.reset()
AdapterManager.get_playlists()
def test_functions_not_implemented():
with pytest.raises(NotImplementedError):
Adapter(None)