add deprecation warnings and FAQ to respond to Spotify's API changes (#1177)

* add deprecation warnings and FAQ to respond to Spotify's API changes

* remove test cases associated with deprecated methods

* added missing commas
This commit is contained in:
Niko 2025-01-03 13:26:08 +01:00 committed by GitHub
parent db3fb9a5ee
commit 14ab13d292
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 46 additions and 70 deletions

View File

@ -19,6 +19,14 @@ Add your changes below.
- Added `personalized_playlist.py`, `track_recommendations.py`, and `audio_features_analysis.py` to `/examples`. - Added `personalized_playlist.py`, `track_recommendations.py`, and `audio_features_analysis.py` to `/examples`.
- Discord badge in README - Discord badge in README
- Added `SpotifyBaseException` and moved all exceptions to `exceptions.py` - Added `SpotifyBaseException` and moved all exceptions to `exceptions.py`
- Marked the following methods as deprecated:
- artist_related_artists
- recommendations
- audio_features
- audio_analysis
- featured_playlists
- category_playlists
- Added FAQ entry for inaccessible playlists
### Fixed ### Fixed
- Audiobook integration tests - Audiobook integration tests

6
FAQ.md
View File

@ -74,3 +74,9 @@ sp = spotipy.Spotify(
) )
``` ```
The error raised is a `spotipy.exceptions.SpotifyException` The error raised is a `spotipy.exceptions.SpotifyException`
### I get a 404 when trying to access a Spotify-owned playlist
Spotify has begun restricting access to algorithmic and Spotify-owned editorial playlists.
Only applications with an existing extended mode will still have access to these playlists.
Read more about this change here: [Introducing some changes to our Web API](https://developer.spotify.com/blog/2024-11-27-changes-to-the-web-api)

View File

@ -458,6 +458,11 @@ class Spotify:
Parameters: Parameters:
- artist_id - the artist ID, URI or URL - artist_id - the artist ID, URI or URL
""" """
warnings.warn(
"You're using `artist_related_artists(...)`, "
"which is marked as deprecated by Spotify.",
DeprecationWarning
)
trid = self._get_id("artist", artist_id) trid = self._get_id("artist", artist_id)
return self._get("artists/" + trid + "/related-artists") return self._get("artists/" + trid + "/related-artists")
@ -1587,6 +1592,11 @@ class Spotify:
(the first object). Use with limit to get the next set of (the first object). Use with limit to get the next set of
items. items.
""" """
warnings.warn(
"You're using `featured_playlists(...)`, "
"which is marked as deprecated by Spotify.",
DeprecationWarning,
)
return self._get( return self._get(
"browse/featured-playlists", "browse/featured-playlists",
locale=locale, locale=locale,
@ -1671,6 +1681,11 @@ class Spotify:
(the first object). Use with limit to get the next set of (the first object). Use with limit to get the next set of
items. items.
""" """
warnings.warn(
"You're using `category_playlists(...)`, "
"which is marked as deprecated by Spotify.",
DeprecationWarning,
)
return self._get( return self._get(
"browse/categories/" + category_id + "/playlists", "browse/categories/" + category_id + "/playlists",
country=country, country=country,
@ -1708,6 +1723,12 @@ class Spotify:
attributes listed in the documentation, these values attributes listed in the documentation, these values
provide filters and targeting on results. provide filters and targeting on results.
""" """
warnings.warn(
"You're using `recommendations(...)`, "
"which is marked as deprecated by Spotify.",
DeprecationWarning,
)
params = dict(limit=limit) params = dict(limit=limit)
if seed_artists: if seed_artists:
params["seed_artists"] = ",".join( params["seed_artists"] = ",".join(
@ -1754,6 +1775,11 @@ class Spotify:
Parameters: Parameters:
- track_id - a track URI, URL or ID - track_id - a track URI, URL or ID
""" """
warnings.warn(
"You're using `audio_analysis(...)`, "
"which is marked as deprecated by Spotify.",
DeprecationWarning,
)
trid = self._get_id("track", track_id) trid = self._get_id("track", track_id)
return self._get("audio-analysis/" + trid) return self._get("audio-analysis/" + trid)
@ -1762,6 +1788,12 @@ class Spotify:
Parameters: Parameters:
- tracks - a list of track URIs, URLs or IDs, maximum: 100 ids - tracks - a list of track URIs, URLs or IDs, maximum: 100 ids
""" """
warnings.warn(
"You're using `audio_features(...)`, "
"which is marked as deprecated by Spotify.",
DeprecationWarning,
)
if isinstance(tracks, str): if isinstance(tracks, str):
trackid = self._get_id("track", tracks) trackid = self._get_id("track", tracks)
results = self._get("audio-features/?ids=" + trackid) results = self._get("audio-features/?ids=" + trackid)

View File

@ -73,34 +73,6 @@ class AuthTestSpotipy(unittest.TestCase):
client_credentials_manager=SpotifyClientCredentials()) client_credentials_manager=SpotifyClientCredentials())
self.spotify.trace = False self.spotify.trace = False
def test_audio_analysis(self):
result = self.spotify.audio_analysis(self.four_tracks[0])
assert ('beats' in result)
def test_audio_features(self):
results = self.spotify.audio_features(self.four_tracks)
self.assertTrue(len(results) == len(self.four_tracks))
for track in results:
assert ('speechiness' in track)
def test_audio_features_with_bad_track(self):
bad_tracks = ['spotify:track:bad']
input = self.four_tracks + bad_tracks
results = self.spotify.audio_features(input)
self.assertTrue(len(results) == len(input))
for track in results[:-1]:
if track is not None:
assert ('speechiness' in track)
self.assertTrue(results[-1] is None)
def test_recommendations(self):
results = self.spotify.recommendations(
seed_tracks=self.four_tracks,
min_danceability=0,
max_loudness=0,
target_popularity=50)
self.assertTrue(len(results['tracks']) == 20)
def test_artist_urn(self): def test_artist_urn(self):
artist = self.spotify.artist(self.radiohead_urn) artist = self.spotify.artist(self.radiohead_urn)
self.assertTrue(artist['name'] == 'Radiohead') self.assertTrue(artist['name'] == 'Radiohead')
@ -179,17 +151,6 @@ class AuthTestSpotipy(unittest.TestCase):
self.assertTrue('tracks' in results) self.assertTrue('tracks' in results)
self.assertTrue(len(results['tracks']) == 10) self.assertTrue(len(results['tracks']) == 10)
def test_artist_related_artists(self):
results = self.spotify.artist_related_artists(self.weezer_urn)
self.assertTrue('artists' in results)
self.assertTrue(len(results['artists']) == 20)
found = False
for artist in results['artists']:
if artist['name'] == 'Jimmy Eat World':
found = True
self.assertTrue(found)
def test_artist_search(self): def test_artist_search(self):
results = self.spotify.search(q='weezer', type='artist') results = self.spotify.search(q='weezer', type='artist')
self.assertTrue('artists' in results) self.assertTrue('artists' in results)

View File

@ -393,33 +393,6 @@ class SpotipyBrowseApiTests(unittest.TestCase):
response = self.spotify.categories(limit=50) response = self.spotify.categories(limit=50)
self.assertLessEqual(len(response['categories']['items']), 50) self.assertLessEqual(len(response['categories']['items']), 50)
def test_category_playlists(self):
response = self.spotify.categories()
category = 'rock'
for cat in response['categories']['items']:
cat_id = cat['id']
if cat_id == category:
response = self.spotify.category_playlists(category_id=cat_id)
self.assertGreater(len(response['playlists']["items"]), 0)
def test_category_playlists_limit_low(self):
response = self.spotify.categories()
category = 'rock'
for cat in response['categories']['items']:
cat_id = cat['id']
if cat_id == category:
response = self.spotify.category_playlists(category_id=cat_id, limit=1)
self.assertEqual(len(response['categories']['items']), 1)
def test_category_playlists_limit_high(self):
response = self.spotify.categories()
category = 'rock'
for cat in response['categories']['items']:
cat_id = cat['id']
if cat_id == category:
response = self.spotify.category_playlists(category_id=cat_id, limit=50)
self.assertLessEqual(len(response['categories']['items']), 50)
def test_new_releases(self): def test_new_releases(self):
response = self.spotify.new_releases() response = self.spotify.new_releases()
self.assertGreater(len(response['albums']['items']), 0) self.assertGreater(len(response['albums']['items']), 0)
@ -432,10 +405,6 @@ class SpotipyBrowseApiTests(unittest.TestCase):
response = self.spotify.new_releases(limit=50) response = self.spotify.new_releases(limit=50)
self.assertLessEqual(len(response['albums']['items']), 50) self.assertLessEqual(len(response['albums']['items']), 50)
def test_featured_releases(self):
response = self.spotify.featured_playlists()
self.assertGreater(len(response['playlists']), 0)
class SpotipyFollowApiTests(unittest.TestCase): class SpotipyFollowApiTests(unittest.TestCase):
@classmethod @classmethod