From 3b7cb9c8c7d7f79f9a4b426416169f4a81b213c1 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 24 Jan 2022 19:04:38 +0200 Subject: [PATCH 1/4] Deprecate is_streamable and is_fulltrack_available --- src/pylast/__init__.py | 50 +++++++++++++++++++++++++++++------------- tests/test_artist.py | 3 ++- tests/test_track.py | 6 +++-- 3 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/pylast/__init__.py b/src/pylast/__init__.py index e32e849..d22bc3a 100644 --- a/src/pylast/__init__.py +++ b/src/pylast/__init__.py @@ -29,6 +29,7 @@ import shelve import ssl import tempfile import time +import warnings import xml.dom from http.client import HTTPSConnection from urllib.parse import quote_plus @@ -1783,13 +1784,18 @@ class Artist(_Taggable): return self.listener_count def is_streamable(self): - """Returns True if the artist is streamable.""" - - return bool( - _number( - _extract(self._request(self.ws_prefix + ".getInfo", True), "streamable") - ) + """Returns True if the artist is streamable: always False because Last.fm has + deprecated the Radio API.""" + warnings.warn( + "Always returns False. Last.fm has deprecated the Radio API and will " + "it at some point. is_streamable() will be removed in pylast 5.0.0. " + "See https://www.last.fm/api/radio and " + "https://support.last.fm/t/" + "is-the-streamable-attribute-broken-it-always-returns-0/39723/3", + DeprecationWarning, + stacklevel=2, ) + return False def get_bio(self, section, language=None): """ @@ -2130,18 +2136,32 @@ class Track(_Opus): return bool(loved) def is_streamable(self): - """Returns True if the track is available at Last.fm.""" - - doc = self._request(self.ws_prefix + ".getInfo", True) - return _extract(doc, "streamable") == "1" + """Returns True if the artist is streamable: always False because Last.fm has + deprecated the Radio API.""" + warnings.warn( + "Always returns False. Last.fm has deprecated the Radio API and will " + "it at some point. is_streamable() will be removed in pylast 5.0.0. " + "See https://www.last.fm/api/radio and " + "https://support.last.fm/t/" + "is-the-streamable-attribute-broken-it-always-returns-0/39723/3", + DeprecationWarning, + stacklevel=2, + ) + return False def is_fulltrack_available(self): - """Returns True if the full track is available for streaming.""" - - doc = self._request(self.ws_prefix + ".getInfo", True) - return ( - doc.getElementsByTagName("streamable")[0].getAttribute("fulltrack") == "1" + """Returns True if the full track is available for streaming: always False + because Last.fm has deprecated the Radio API.""" + warnings.warn( + "Always returns False. Last.fm has deprecated the Radio API and will " + "remove it at some point. is_fulltrack_available() will be removed in " + "pylast 5.0.0. See https://www.last.fm/api/radio and " + "https://support.last.fm/t/" + "is-the-streamable-attribute-broken-it-always-returns-0/39723/3", + DeprecationWarning, + stacklevel=2, ) + return False def get_album(self): """Returns the album object of this track.""" diff --git a/tests/test_artist.py b/tests/test_artist.py index a911882..463af69 100755 --- a/tests/test_artist.py +++ b/tests/test_artist.py @@ -229,7 +229,8 @@ class TestPyLastArtist(TestPyLastWithLastFm): mbid = artist1.get_mbid() playcount = artist1.get_playcount() - streamable = artist1.is_streamable() + with pytest.warns(DeprecationWarning): + streamable = artist1.is_streamable() name = artist1.get_name(properly_capitalized=False) name_cap = artist1.get_name(properly_capitalized=True) diff --git a/tests/test_track.py b/tests/test_track.py index b56c018..e7ea5e3 100755 --- a/tests/test_track.py +++ b/tests/test_track.py @@ -123,7 +123,8 @@ class TestPyLastTrack(TestPyLastWithLastFm): track = pylast.Track("Nirvana", "Lithium", self.network) # Act - streamable = track.is_streamable() + with pytest.warns(DeprecationWarning): + streamable = track.is_streamable() # Assert assert not streamable @@ -133,7 +134,8 @@ class TestPyLastTrack(TestPyLastWithLastFm): track = pylast.Track("Nirvana", "Lithium", self.network) # Act - fulltrack_available = track.is_fulltrack_available() + with pytest.warns(DeprecationWarning): + fulltrack_available = track.is_fulltrack_available() # Assert assert not fulltrack_available From d672e89f233424eb564f127c260aafaee7714ce7 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 24 Jan 2022 21:15:11 +0200 Subject: [PATCH 2/4] Is an xfail passing unexpectedly? Make it fail --- pytest.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pytest.ini b/pytest.ini index 34667c8..3f83bd3 100644 --- a/pytest.ini +++ b/pytest.ini @@ -2,3 +2,5 @@ filterwarnings = once::DeprecationWarning once::PendingDeprecationWarning + +xfail_strict=true From 1841fb66dc9c2b15a803c0c56f4bb9c50907aeb3 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 24 Jan 2022 22:07:03 +0200 Subject: [PATCH 3/4] This test now passes, although some other MBID searches are still broken --- tests/test_network.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/test_network.py b/tests/test_network.py index 2ed839f..2f743ab 100755 --- a/tests/test_network.py +++ b/tests/test_network.py @@ -267,8 +267,6 @@ class TestPyLastNetwork(TestPyLastWithLastFm): assert isinstance(artist, pylast.Artist) assert artist.name in ("MusicBrainz Test Artist", "MusicBrainzz Test Artist") - @pytest.mark.xfail(reason="Broken at Last.fm: Track not found") - # https://support.last.fm/t/track-getinfo-with-mbid-returns-6-track-not-found/47905 def test_track_mbid(self): # Arrange mbid = "ebc037b1-cc9c-44f2-a21f-83c219f0e1e0" From 3ffe7cf65ac4336322958367d284f158c0c6c104 Mon Sep 17 00:00:00 2001 From: Hugo van Kemenade Date: Mon, 24 Jan 2022 22:26:16 +0200 Subject: [PATCH 4/4] test_get_userplaycount now passes --- tests/test_artist.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/tests/test_artist.py b/tests/test_artist.py index 463af69..8cc4f85 100755 --- a/tests/test_artist.py +++ b/tests/test_artist.py @@ -268,7 +268,6 @@ class TestPyLastArtist(TestPyLastWithLastFm): # Assert assert corrected_artist_name == "Guns N' Roses" - @pytest.mark.xfail def test_get_userplaycount(self): # Arrange artist = pylast.Artist("John Lennon", self.network, username=self.username) @@ -277,4 +276,4 @@ class TestPyLastArtist(TestPyLastWithLastFm): playcount = artist.get_userplaycount() # Assert - assert playcount >= 0 # whilst xfail: # pragma: no cover + assert playcount >= 0