Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions lyricsgenius/genius.py
Original file line number Diff line number Diff line change
Expand Up @@ -352,6 +352,7 @@ def search_album(
album_id: int | None = None,
get_full_info: bool = True,
text_format: TextFormatT | None = None,
fetch_lyrics: bool = True,
) -> Album | None:
"""Searches for a specific album and gets its songs.

Expand All @@ -365,6 +366,10 @@ def search_album(
for the album (slower if no album_id present).
text_format (:obj:`str`, optional): Text format of the results
('dom', 'html', 'markdown' or 'plain').
fetch_lyrics (:obj:`bool`, optional): If `True` (default), scrapes
lyrics for each track. Set to `False` to skip lyrics fetching
and return only track metadata — significantly faster for large
albums.

Returns:
:class:`Album <types.Album>` \\| :obj:`None`: On success,
Expand Down Expand Up @@ -431,8 +436,10 @@ def search_album(
for track_data in tracks_list_response["tracks"]:
song_info = track_data["song"]
song_lyrics = None
if song_info["lyrics_state"] == "complete" and not song_info.get(
"instrumental"
if (
fetch_lyrics
and song_info["lyrics_state"] == "complete"
and not song_info.get("instrumental")
):
song_lyrics = self.lyrics(song_url=song_info["url"])

Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "hatchling.build"

[project]
name = "lyricsgenius"
version = "3.10.0"
version = "3.10.1"
dependencies = ["beautifulsoup4>=4.12.3", "requests>=2.27.1"]
requires-python = ">=3.11"
authors = [{ name = "John W. R. Miller", email = "john.w.millr+lg@gmail.com" }]
Expand Down
91 changes: 91 additions & 0 deletions tests/test_album.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import pytest

from lyricsgenius import Genius
from lyricsgenius.types import Album, Artist, Song
from lyricsgenius.utils import sanitize_filename

Expand Down Expand Up @@ -213,3 +214,93 @@ def test_saving_txt_file(album_object: Album, tmp_path: Path) -> None:
content_after_overwrite = expected_filepath.read_text()
assert "Overwritten TXT Test" in content_after_overwrite, content_after_overwrite
album_object.tracks[0][1].lyrics = original_lyrics


@pytest.fixture
def genius_client() -> Genius:
return Genius("dummy_access_token", verbose=False, sleep_time=0)


def _make_search_all_response(album_data: dict[str, Any]) -> dict[str, Any]:
hit = {"index": "album", "result": album_data}
return {
"sections": [
{"type": "top_hits", "hits": [hit]},
{"type": "album", "hits": [hit]},
]
}


def _make_album_tracks_response(songs: list[dict[str, Any]]) -> dict[str, Any]:
return {
"tracks": [{"song": s, "number": i + 1} for i, s in enumerate(songs)],
"next_page": None,
}


def test_fetch_lyrics_true_calls_lyrics(
genius_client: Genius,
mock_album_data: dict[str, Any],
mock_track_data_list: list[dict[str, Any]],
) -> None:
"""When fetch_lyrics=True (default), lyrics() should be called for each track."""
with (
mock.patch.object(
genius_client,
"search_all",
return_value=_make_search_all_response(mock_album_data),
),
mock.patch.object(
genius_client, "album", return_value={"album": mock_album_data}
),
mock.patch.object(
genius_client,
"album_tracks",
return_value=_make_album_tracks_response(mock_track_data_list),
),
mock.patch.object(
genius_client, "lyrics", return_value="some lyrics"
) as mock_lyrics,
):
result = genius_client.search_album(
name=mock_album_data["name"], fetch_lyrics=True
)

assert result is not None
assert mock_lyrics.call_count == len(mock_track_data_list)
for _, track in result.tracks:
assert track.lyrics == "some lyrics"


def test_fetch_lyrics_false_skips_lyrics(
genius_client: Genius,
mock_album_data: dict[str, Any],
mock_track_data_list: list[dict[str, Any]],
) -> None:
"""When fetch_lyrics=False, lyrics() is not called and tracks have empty lyrics."""
with (
mock.patch.object(
genius_client,
"search_all",
return_value=_make_search_all_response(mock_album_data),
),
mock.patch.object(
genius_client, "album", return_value={"album": mock_album_data}
),
mock.patch.object(
genius_client,
"album_tracks",
return_value=_make_album_tracks_response(mock_track_data_list),
),
mock.patch.object(
genius_client, "lyrics", return_value="some lyrics"
) as mock_lyrics,
):
result = genius_client.search_album(
name=mock_album_data["name"], fetch_lyrics=False
)

assert result is not None
assert mock_lyrics.call_count == 0
for _, track in result.tracks:
assert track.lyrics == ""
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.