Skip to content

Commit

Permalink
Merge pull request #35 from hudsonbrendon/feat/track_search
Browse files Browse the repository at this point in the history
feat: refactor method track_search
  • Loading branch information
hudsonbrendon authored Jan 3, 2025
2 parents d82b6cf + 787468f commit 7e650b6
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 49 deletions.
5 changes: 5 additions & 0 deletions pymusixmatch/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,8 @@ class Country(Enum):
class Format(Enum):
JSON = "json"
XML = "xml"


class Ordering(Enum):
ASC = "asc"
DESC = "desc"
105 changes: 65 additions & 40 deletions pymusixmatch/musixmatch.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from typing import Optional
import requests

from pymusixmatch.enums import Country, Format, Route
from pymusixmatch.enums import Country, Format, Ordering, Route


class Musixmatch(object):
Expand Down Expand Up @@ -103,7 +103,7 @@ def chart_tracks_get(
f_has_lyrics: bool,
country: Optional[Country] = Country.US.value,
_format: Optional[Format] = Format.JSON.value,
):
) -> dict:
"""This api provides you the list
of the top songs of a given country.
Expand Down Expand Up @@ -132,54 +132,79 @@ def chart_tracks_get(

def track_search(
self,
q_track,
q_artist,
page_size,
page,
s_track_rating,
_format="json",
):
page: int,
page_size: int,
q_track: Optional[str] = "",
q_artist: Optional[str] = "",
q_lyrics: Optional[str] = "",
q_track_artist: Optional[str] = "",
q_writer: Optional[str] = "",
q: Optional[str] = "",
f_artist_id: Optional[int] = "",
f_music_genre_id: Optional[int] = "",
f_lyrics_language: Optional[str] = "",
f_has_lyrics: Optional[bool] = "",
f_track_release_group_first_release_date_min: Optional[str] = "",
f_track_release_group_first_release_date_max: Optional[str] = "",
s_artist_rating: Optional[Ordering] = Ordering.DESC.value,
s_track_rating: Optional[Ordering] = Ordering.DESC.value,
quorum_factor: Optional[float] = "",
) -> dict:
"""Search for track in our database.
Parameters:
q_track - The song title.
q_artist - The song artist.
q_lyrics - Any word in the lyrics.
f_artist_id - When set, filter by this artist id.
f_music_genre_id - When set, filter by this music category id.
f_lyrics_language - Filter by the lyrics language (en,it,..).
f_has_lyrics - When set, filter only contents with lyrics.
f_track_release_group_first_release_date_min - When set, filter
the tracks with release date newer than value, format is YYYYMMDD.
f_track_release_group_first_release_date_max - When set, filter
the tracks with release date older than value, format is YYYYMMDD.
s_artist_rating - Sort by our popularity index for artists (asc|desc).
s_track_rating - Sort by our popularity index for tracks (asc|desc).
quorum_factor - Search only a part of the given query string.
Allowed range is (0.1 – 0.9).
page - Define the page number for paginated results.
page_size - Define the page size for paginated results.
Range is 1 to 100.
callback - jsonp callback.
format - Decide the output type json or xml (default json).
q_track (str): The song title
q_artist (str): The song artist
q_lyrics (str): Any word in the lyrics
q_track_artist (str): Any word in the song title or artist name
q_writer (str): Search among writers
q (str): Any word in the song title or artist name or lyrics
f_artist_id (int): When set, filter by this artist id
f_music_genre_id (int): When set, filter by this music category id
f_lyrics_language (str): Filter by the lyrics language (en,it,..)
f_has_lyrics (bool): When set, filter only contents with lyrics
f_track_release_group_first_release_date_min (str): When set, filter the tracks with release date newer than value, format is YYYYMMDD
f_track_release_group_first_release_date_max (str): When set, filter the tracks with release date older than value, format is YYYYMMDD
s_artist_rating (Ordering): Sort by our popularity index for artists (asc|desc)
s_track_rating (Ordering): Sort by our popularity index for tracks (asc|desc)
quorum_factor (float): Search only a part of the given query string.Allowed range is (0.1 – 0.9)
page (int): Define the page number for paginated results
page_size (int): Define the page size for paginated results. Range is 1 to 100.
Note: This method requires a commercial plan.
"""

if s_artist_rating not in Ordering._value2member_map_:
raise ValueError(
f"Invalid artist rating: {s_artist_rating}, please use a valid artist rating."
)

if s_track_rating not in Ordering._value2member_map_:
raise ValueError(
f"Invalid track rating: {s_track_rating}, please use a valid track rating."
)

data = self._request(
self._get_url(
"track.search?"
"q_track={}&q_artist={}"
"&page_size={}"
"&page={}"
"&s_track_rating={}&format={}".format(
q_track,
q_artist,
self._set_page_size(page_size),
page,
s_track_rating,
_format,
),
f"q_track={q_track}&"
f"q_artist={q_artist}&"
f"q_lyrics={q_lyrics}&"
f"q_track_artist={q_track_artist}&"
f"q_writer={q_writer}&"
f"q={q}&"
f"f_artist_id={f_artist_id}&"
f"f_music_genre_id={f_music_genre_id}&"
f"f_lyrics_language={f_lyrics_language}&"
f"f_has_lyrics={f_has_lyrics}&"
f"f_track_release_group_first_release_date_min={f_track_release_group_first_release_date_min}&"
f"f_track_release_group_first_release_date_max={f_track_release_group_first_release_date_max}&"
f"s_artist_rating={s_artist_rating}&"
f"s_track_rating={s_track_rating}&"
f"quorum_factor={quorum_factor}&"
f"page={page}&"
f"page_size={self._set_page_size(page_size)}"
),
)
return data
Expand Down
16 changes: 16 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -82,3 +82,19 @@ def track_snippet() -> dict:
},
}
}


@pytest.fixture
def track_search() -> dict:
return {
"message": {
"header": {"status_code": 200, "execute_time": 0.00136, "available": 646},
"body": {
"track_list": [
{"track": "track'"},
{"track": "track'"},
{"track": "track'"},
]
},
}
}
63 changes: 54 additions & 9 deletions tests/test_musixmatch.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ def test_set_page_size_with_invalid_page_size(
def test_chart_artists(self, requests_mock, chart_artists: dict) -> None:
url = "https://api.musixmatch.com/ws/1.1/chart.artists.get?page=1&page_size=1&country=us&format=json"
requests_mock.get(url=url, json=chart_artists)
request = self.musixmatch.chart_artists(1, 1)
assert chart_artists == request
assert chart_artists == self.musixmatch.chart_artists(1, 1)

def test_chart_artists_with_invalid_country(
self, requests_mock, chart_artists: dict
Expand All @@ -62,8 +61,7 @@ def test_chart_artists_with_invalid_format(
def test_chart_tracks_get(self, requests_mock, tracks: dict) -> None:
url = "https://api.musixmatch.com/ws/1.1/chart.tracks.get?page=1&page_size=1&country=us&format=json&f_has_lyrics=1"
requests_mock.get(url=url, json=tracks)
request = self.musixmatch.chart_tracks_get(1, 1, 1)
assert tracks == request
assert tracks == self.musixmatch.chart_tracks_get(1, 1, 1)

def test_chart_tracks_get_with_invalid_country(
self, requests_mock, tracks: dict
Expand All @@ -81,19 +79,66 @@ def test_chart_tracks_get_with_invalid_format(
with pytest.raises(ValueError):
self.musixmatch.chart_tracks_get(1, 1, 1, _format="invalid")

@pytest.mark.skip("Refactor test")
def test_track_search(self):
self.assertEqual(
def test_track_search(self, requests_mock, track_search: dict) -> None:
url = "https://api.musixmatch.com/ws/1.1/track.search?q_track=Let%20Me%20Love%20You&q_artist=justinbieber&q_lyrics=&q_track_artist=&q_writer=&q=&f_artist_id=&f_music_genre_id=&f_lyrics_language=&f_has_lyrics=&f_track_release_group_first_release_date_min=&f_track_release_group_first_release_date_max=&s_artist_rating=desc&s_track_rating=desc&quorum_factor=&page=1&page_size=10&apikey=test"
requests_mock.get(url=url, json=track_search)

assert (
self.musixmatch.track_search(
q_track="Let Me Love You",
q_artist="justinbieber",
page_size=10,
page=1,
s_track_rating="desc",
)["message"]["body"]["track_list"],
[],
)
== track_search
)

def test_track_search_with_invalid_page_size(
self, requests_mock, track_search: dict
) -> None:
url = "https://api.musixmatch.com/ws/1.1/track.search?q_track=Let%20Me%20Love%20You&q_artist=justinbieber&q_lyrics=&q_track_artist=&q_writer=&q=&f_artist_id=&f_music_genre_id=&f_lyrics_language=&f_has_lyrics=&f_track_release_group_first_release_date_min=&f_track_release_group_first_release_date_max=&s_artist_rating=desc&s_track_rating=desc&quorum_factor=&page=1&page_size=101&apikey=test"
requests_mock.get(url=url, json=track_search)

with pytest.raises(ValueError):
self.musixmatch.track_search(
q_track="Let Me Love You",
q_artist="justinbieber",
page_size=101,
page=1,
s_track_rating="desc",
)

def test_track_search_with_invalid_s_artist_rating(
self, requests_mock, track_search: dict
) -> None:
url = "https://api.musixmatch.com/ws/1.1/track.search?q_track=Let%20Me%20Love%20You&q_artist=justinbieber&q_lyrics=&q_track_artist=&q_writer=&q=&f_artist_id=&f_music_genre_id=&f_lyrics_language=&f_has_lyrics=&f_track_release_group_first_release_date_min=&f_track_release_group_first_release_date_max=&s_artist_rating=invalid&s_track_rating=desc&quorum_factor=&page=1&page_size=10&apikey=test"
requests_mock.get(url=url, json=track_search)

with pytest.raises(ValueError):
self.musixmatch.track_search(
q_track="Let Me Love You",
q_artist="justinbieber",
page_size=10,
page=1,
s_artist_rating="invalid",
)

def test_track_search_with_invalid_s_track_rating(
self, requests_mock, track_search: dict
) -> None:
url = "https://api.musixmatch.com/ws/1.1/track.search?q_track=Let%20Me%20Love%20You&q_artist=justinbieber&q_lyrics=&q_track_artist=&q_writer=&q=&f_artist_id=&f_music_genre_id=&f_lyrics_language=&f_has_lyrics=&f_track_release_group_first_release_date_min=&f_track_release_group_first_release_date_max=&s_artist_rating=desc&s_track_rating=invalid&quorum_factor=&page=1&page_size=10&apikey=test"
requests_mock.get(url=url, json=track_search)

with pytest.raises(ValueError):
self.musixmatch.track_search(
q_track="Let Me Love You",
q_artist="justinbieber",
page_size=10,
page=1,
s_track_rating="invalid",
)

@pytest.mark.skip("Refactor test")
def test_track_get(self):
self.assertEqual(
Expand Down

0 comments on commit 7e650b6

Please sign in to comment.