Skip to content

Commit

Permalink
please the linter
Browse files Browse the repository at this point in the history
  • Loading branch information
heinrich26 authored and sigma67 committed Dec 17, 2024
1 parent fc1dec4 commit 347c2e6
Show file tree
Hide file tree
Showing 8 changed files with 45 additions and 34 deletions.
2 changes: 1 addition & 1 deletion tests/mixins/test_browsing.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,7 @@ def test_get_lyrics(self, config, yt, sample_video):
assert lyrics_song["hasTimestamps"] is False

# test lyrics with timestamps
lyrics_song = yt.get_lyrics(playlist["lyrics"], timestamps = True)
lyrics_song = yt.get_lyrics(playlist["lyrics"], timestamps=True)
assert lyrics_song is not None
assert len(lyrics_song["lyrics"]) >= 1
assert lyrics_song["hasTimestamps"] is True
Expand Down
3 changes: 1 addition & 2 deletions ytmusicapi/mixins/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

from ytmusicapi.exceptions import YTMusicUserError


LibraryOrderType = Literal['a_to_z', 'z_to_a', 'recently_added']
LibraryOrderType = Literal["a_to_z", "z_to_a", "recently_added"]


def prepare_like_endpoint(rating):
Expand Down
20 changes: 9 additions & 11 deletions ytmusicapi/mixins/browsing.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import re
import warnings
from typing import Any, cast, Optional, Union
from typing import Any, Optional, Union, cast, overload

from ytmusicapi.continuations import (
get_continuations,
get_reloadable_continuation_params,
)
from ytmusicapi.helpers import YTM_DOMAIN, sum_total_duration
from ytmusicapi.models.lyrics import Lyrics, LyricLine, TimedLyrics
from ytmusicapi.models.lyrics import LyricLine, Lyrics, TimedLyrics
from ytmusicapi.parsers.albums import parse_album_header_2024
from ytmusicapi.parsers.browsing import (
parse_album,
Expand Down Expand Up @@ -277,7 +277,7 @@ def get_artist(self, channelId: str) -> dict:
artist.update(self.parser.parse_channel_contents(results))
return artist

ArtistOrderType = Literal['Recency', 'Popularity', 'Alphabetical order']
ArtistOrderType = Literal["Recency", "Popularity", "Alphabetical order"]

def get_artist_albums(
self, channelId: str, params: str, limit: Optional[int] = 100, order: Optional[ArtistOrderType] = None
Expand Down Expand Up @@ -839,34 +839,33 @@ def get_song_related(self, browseId: str):
sections = nav(response, ["contents", *SECTION_LIST])
return parse_mixed_content(sections)


@overload
def get_lyrics(self, browseId: str, timestamps: Literal[False] = False) -> Optional[Lyrics]:
"""overload for mypy only"""

@overload
def get_lyrics(self, browseId: str, timestamps: Literal[True] = True) -> Optional[Lyrics|TimedLyrics]:
def get_lyrics(self, browseId: str, timestamps: Literal[True] = True) -> Optional[Lyrics | TimedLyrics]:
"""overload for mypy only"""

def get_lyrics(self, browseId: str, timestamps: Optional[bool] = False) -> Optional[Lyrics|TimedLyrics]:
def get_lyrics(self, browseId: str, timestamps: Optional[bool] = False) -> Optional[Lyrics | TimedLyrics]:
"""
Returns lyrics of a song or video. When `timestamps` is set, lyrics are returned with
timestamps, if available.
:param browseId: Lyrics browse-id obtained from :py:func:`get_watch_playlist` (startswith `MPLYt...`).
:param timestamps: Optional. Whether to return bare lyrics or lyrics with timestamps, if available. (Default: `False`)
:return: Dictionary with song lyrics or `None`, if no lyrics are found.
:return: Dictionary with song lyrics or `None`, if no lyrics are found.
The `hasTimestamps`-key determines the format of the data.
Example when `timestamps=False`, or no timestamps are available::
{
"lyrics": "Today is gonna be the day\\nThat they're gonna throw it back to you\\n",
"source": "Source: LyricFind",
"hasTimestamps": False
}
Example when `timestamps` is set to `True` and timestamps are available::
{
Expand All @@ -892,8 +891,7 @@ def get_lyrics(self, browseId: str, timestamps: Optional[bool] = False) -> Optio

lyrics: dict = {}
if not browseId:
raise YTMusicUserError(
"Invalid browseId provided. This song might not have lyrics.")
raise YTMusicUserError("Invalid browseId provided. This song might not have lyrics.")

if timestamps:
# changes and restores the client to get lyrics with timestamps (mobile only)
Expand Down
4 changes: 3 additions & 1 deletion ytmusicapi/mixins/library.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,9 @@ def get_library_artists(self, limit: int = 25, order: Optional[LibraryOrderType]
response, lambda additionalParams: self._send_request(endpoint, body, additionalParams), limit
)

def get_library_subscriptions(self, limit: int = 25, order: Optional[LibraryOrderType] = None) -> list[dict]:
def get_library_subscriptions(
self, limit: int = 25, order: Optional[LibraryOrderType] = None
) -> list[dict]:
"""
Gets the artists the user has subscribed to.
Expand Down
8 changes: 6 additions & 2 deletions ytmusicapi/mixins/uploads.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@


class UploadsMixin(MixinProtocol):
def get_library_upload_songs(self, limit: Optional[int] = 25, order: Optional[LibraryOrderType] = None) -> list[dict]:
def get_library_upload_songs(
self, limit: Optional[int] = 25, order: Optional[LibraryOrderType] = None
) -> list[dict]:
"""
Returns a list of uploaded songs
Expand Down Expand Up @@ -70,7 +72,9 @@ def get_library_upload_songs(self, limit: Optional[int] = 25, order: Optional[Li

return songs

def get_library_upload_albums(self, limit: Optional[int] = 25, order: Optional[LibraryOrderType] = None) -> list[dict]:
def get_library_upload_albums(
self, limit: Optional[int] = 25, order: Optional[LibraryOrderType] = None
) -> list[dict]:
"""
Gets the albums of uploaded songs in the user's library.
Expand Down
3 changes: 2 additions & 1 deletion ytmusicapi/models/lyrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,14 @@
@dataclass
class LyricLine:
"""Represents a line of lyrics with timestamps (in milliseconds).
Args:
text (str): The Songtext.
start_time (int): Begin of the lyric in milliseconds.
end_time (int): End of the lyric in milliseconds.
id (int): A Metadata-Id that probably uniquely identifies each lyric line.
"""

text: str
start_time: int
end_time: int
Expand Down
12 changes: 10 additions & 2 deletions ytmusicapi/navigation.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,16 @@
CAROUSEL_TITLE = [*HEADER, "musicCarouselShelfBasicHeaderRenderer", *TITLE]
CARD_SHELF_TITLE = [*HEADER, "musicCardShelfHeaderBasicRenderer", *TITLE_TEXT]
FRAMEWORK_MUTATIONS = ["frameworkUpdates", "entityBatchUpdate", "mutations"]
TIMESTAMPED_LYRICS = ["contents", "elementRenderer", "newElement", "type",
"componentType", "model", "timedLyricsModel", "lyricsData"]
TIMESTAMPED_LYRICS = [
"contents",
"elementRenderer",
"newElement",
"type",
"componentType",
"model",
"timedLyricsModel",
"lyricsData",
]


@overload
Expand Down
27 changes: 13 additions & 14 deletions ytmusicapi/ytmusic.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
import json
import locale
import time
from contextlib import suppress, contextmanager
from contextlib import contextmanager, suppress
from functools import partial
from pathlib import Path
from typing import cast, Optional, Union
from typing import Optional, Union, cast

import requests
from requests import Response
Expand Down Expand Up @@ -189,14 +189,16 @@ def base_headers(self):
if self.auth_type == AuthType.BROWSER or self.auth_type == AuthType.OAUTH_CUSTOM_FULL:
self._base_headers = self._input_dict
else:
self._base_headers = CaseInsensitiveDict({
"user-agent": USER_AGENT,
"accept": "*/*",
"accept-encoding": "gzip, deflate",
"content-type": "application/json",
"content-encoding": "gzip",
"origin": YTM_DOMAIN,
})
self._base_headers = CaseInsensitiveDict(
{
"user-agent": USER_AGENT,
"accept": "*/*",
"accept-encoding": "gzip, deflate",
"content-type": "application/json",
"content-encoding": "gzip",
"origin": YTM_DOMAIN,
}
)

return cast(CaseInsensitiveDict[str], self._base_headers)

Expand Down Expand Up @@ -243,10 +245,7 @@ def as_mobile(self):

# change the context to emulate a mobile-app (Android)
copied_context_client = self.context["context"]["client"].copy()
self.context["context"]["client"].update({
"clientName": "ANDROID_MUSIC",
"clientVersion": "7.21.50"
})
self.context["context"]["client"].update({"clientName": "ANDROID_MUSIC", "clientVersion": "7.21.50"})

# this will not catch errors
try:
Expand Down

0 comments on commit 347c2e6

Please sign in to comment.