Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' into master
Browse files Browse the repository at this point in the history
stephanebruckert authored Jan 12, 2025

Verified

This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
2 parents 767b3f2 + ba01a6a commit 7fc5ea8
Showing 23 changed files with 324 additions and 129 deletions.
20 changes: 19 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -8,6 +8,17 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
Add your changes below.

### Added
- Added examples for audiobooks, shows and episodes methods to examples directory

### Fixed
- Fixed scripts in examples directory that didn't run correctly
- Updated documentation for `Client.current_user_top_artists` to indicate maximum number of artists limit

### Removed

## [2.25.0] - 2025-03-01

### Added
- Added unit tests for queue functions
- Added detailed function docstrings to 'util.py', including descriptions and special sections that lists arguments, returns, and raises.
@@ -19,7 +30,14 @@ Add your changes below.
- Added `personalized_playlist.py`, `track_recommendations.py`, and `audio_features_analysis.py` to `/examples`.
- Discord badge in README
- Added `SpotifyBaseException` and moved all exceptions to `exceptions.py`
- Updated documentation for `Client.current_user_top_artists` to indicate maximum number of artists limit
- 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
- Audiobook integration tests
6 changes: 6 additions & 0 deletions FAQ.md
Original file line number Diff line number Diff line change
@@ -74,3 +74,9 @@ sp = spotipy.Spotify(
)
```
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)
28 changes: 28 additions & 0 deletions examples/add_saved_episodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
Add episodes to current user's library
Usage: add_saved_episodes.py -e episode_id episode_id ...
"""

import argparse
import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = 'user-library-modify'

def get_args():
parser = argparse.ArgumentParser(description='Add episodes to library')
# Default args set to This American Life episodes 814 and 815
parser.add_argument('-e', '--eids', nargs='+',
default=['6rxg9Lpt2ywNHFea8LxEBO', '7q8or6oYYRFQFYlA0remoy'],
help='Episode ids')
return parser.parse_args()

def main():
args = get_args()
print('Adding following episode ids to library: ' + str(args.eids))
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))
sp.current_user_saved_episodes_add(episodes=args.eids)


if __name__ == '__main__':
main()
28 changes: 28 additions & 0 deletions examples/add_saved_shows.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
Add shows to current user's library
Usage: add_saved_shows.py -s show_id show_id ...
"""

import argparse
import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = 'user-library-modify'

def get_args():
parser = argparse.ArgumentParser(description='Add shows to library')
# Default args set to Radiolab and 99% invisible
parser.add_argument('-s', '--sids', nargs='+',
default=['2hmkzUtix0qTqvtpPcMzEL', '2VRS1IJCTn2Nlkg33ZVfkM'],
help='Show ids')
return parser.parse_args()

def main():
args = get_args()
print('Adding following show ids to library: ' + str(args.sids))
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))
sp.current_user_saved_shows_add(shows=args.sids)


if __name__ == '__main__':
main()
31 changes: 31 additions & 0 deletions examples/check_show_is_saved.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""
Check if shows are saved in user's library
Usage: check_show_is_saved -s show_id show_id ...
"""

import argparse
import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = 'user-library-read'

def get_args():
parser = argparse.ArgumentParser(description='Check that a show is saved')
# Default args set to Radiolab and 99% invisible
parser.add_argument('-s', '--sids', nargs='+',
default=['2hmkzUtix0qTqvtpPcMzEL', '2VRS1IJCTn2Nlkg33ZVfkM'],
help='Show ids')
return parser.parse_args()

def main():
args = get_args()
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))
results = sp.current_user_saved_episodes_contains(episodes=args.sids)
show_names = sp.shows(shows=args.sids)
# Print show names and if show is saved by current user
for i, show in enumerate(show_names['shows']):
print(show['name'] + ': ' + str(results[i]))


if __name__ == '__main__':
main()
28 changes: 28 additions & 0 deletions examples/delete_saved_episodes.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""
Delete episodes from current user's library
Usage: delete_saved_episodes.py -e episode_id episode_id ...
"""

import argparse
import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = 'user-library-modify'

def get_args():
parser = argparse.ArgumentParser(description='Delete episodes from library')
# Default args set to This American Life episodes 814 and 815
parser.add_argument('-e', '--eids', nargs='+',
default=['6rxg9Lpt2ywNHFea8LxEBO', '7q8or6oYYRFQFYlA0remoy'],
help='Episode ids')
return parser.parse_args()

def main():
args = get_args()
print('Deleting following episode ids from library: ' + str(args.eids))
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))
sp.current_user_saved_episodes_delete(episodes=args.eids)


if __name__ == '__main__':
main()
21 changes: 8 additions & 13 deletions examples/follow_playlist.py
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
import argparse
# Follow a playlist

import argparse
import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = 'playlist-modify-public'
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))

def get_args():
parser = argparse.ArgumentParser(description='Follows a playlist based on playlist ID')
parser.add_argument('-p', '--playlist', required=True, help='Playlist ID')

# Default to Top 50 Global if no playlist is provided
parser.add_argument('-p', '--playlist', help='Playlist ID', nargs='?', default='37i9dQZEVXbMDoHDwVN2tF')
return parser.parse_args()


def main():
args = get_args()

if args.playlist is None:
# Uses the Spotify Global Top 50 playlist
spotipy.Spotify(auth_manager=SpotifyOAuth()).current_user_follow_playlist(
'37i9dQZEVXbMDoHDwVN2tF')

else:
spotipy.Spotify(auth_manager=SpotifyOAuth()).current_user_follow_playlist(args.playlist)

sp.current_user_follow_playlist(args.playlist)

if __name__ == '__main__':
main()
main()
29 changes: 29 additions & 0 deletions examples/get_audiobook_chapters_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Print chapter titles and lengths for given audiobook
Usage: get_audiobooks_chapters_info.py -a audiobook_id
"""

import argparse
import spotipy
from spotipy.oauth2 import SpotifyOAuth


def get_args():
parser = argparse.ArgumentParser(description='Get chapter info for an audiobook')
# Default set to Dune
parser.add_argument('-a', '--audiobook', default='2h01INWMBvfpzNMpGFzhdF', help='Audiobook id')
return parser.parse_args()


def main():
args = get_args()
print('Getting chapter info for follow audiobook id: ' + str(args.audiobook))
sp = spotipy.Spotify(auth_manager=SpotifyOAuth())
results = sp.get_audiobook_chapters(id=args.audiobook)
# Print chapter name and length
for item in results['items']:
print('Name: ' + item['name'] + ', length: ' + str(round(item['duration_ms']/60000,1)) + ' minutes')


if __name__ == '__main__':
main()
29 changes: 29 additions & 0 deletions examples/get_audiobooks_info.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""
Print audiobook title and description for a list of audiobook ids
Usage: get_audiobooks_info.py -a audiobook_id audiobook_id ...
"""

import argparse
import spotipy
from spotipy.oauth2 import SpotifyOAuth

def get_args():
parser = argparse.ArgumentParser(description='Get information for a list of audiobooks')
# Defaults set to The Great Gatsby, The Chronicles of Narnia and Dune
parser.add_argument('-a', '--aids', nargs='+',
default=['6qjpt1CUHhKXiNoeNoU7nu', '1ezmXd68LbDtxebvygEQ2U', '2h01INWMBvfpzNMpGFzhdF'],
help='Audiobook ids')
return parser.parse_args()

def main():
args = get_args()
print('Getting info for follow audiobook ids: ' + str(args.aids) + '\n')
sp = spotipy.Spotify(auth_manager=SpotifyOAuth())
results = sp.get_audiobooks(ids=args.aids)
# Print book title and description
for book in results['audiobooks']:
print('Title: ' + book['name'] + '\n' + book['description'] + '\n')


if __name__ == '__main__':
main()
12 changes: 0 additions & 12 deletions examples/playlist_add_items.py

This file was deleted.

2 changes: 1 addition & 1 deletion examples/read_a_playlist.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,6 @@
client_credentials_manager = SpotifyClientCredentials()
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)

playlist_id = 'spotify:user:spotifycharts:playlist:37i9dQZEVXbJiZcmkrIHGU'
playlist_id = '37i9dQZEVXbJiZcmkrIHGU'
results = sp.playlist(playlist_id)
print(json.dumps(results, indent=4))
4 changes: 2 additions & 2 deletions examples/remove_tracks_from_playlist.py
Original file line number Diff line number Diff line change
@@ -7,8 +7,8 @@


if len(sys.argv) > 2:
playlist_id = sys.argv[2]
track_ids = sys.argv[3:]
playlist_id = sys.argv[1]
track_ids = sys.argv[2:]
else:
print(f"Usage: {sys.argv[0]} playlist_id track_id ...")
sys.exit()
2 changes: 1 addition & 1 deletion examples/replace_tracks_in_playlist.py
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@
import spotipy
from spotipy.oauth2 import SpotifyOAuth

if len(sys.argv) > 3:
if len(sys.argv) > 2:
playlist_id = sys.argv[1]
track_ids = sys.argv[2:]
else:
File renamed without changes.
34 changes: 19 additions & 15 deletions examples/show_tracks.py
Original file line number Diff line number Diff line change
@@ -3,21 +3,25 @@
given a list of track IDs show the artist and track name
'''
from spotipy.oauth2 import SpotifyClientCredentials
import sys
from spotipy.oauth2 import SpotifyOAuth
import spotipy
import argparse


def get_args():
parser = argparse.ArgumentParser(description='Print artist and track name given a list of track IDs')
parser.add_argument('-u', '--uris', nargs='+',
required=True, help='Track ids')
return parser.parse_args()

if __name__ == '__main__':
max_tracks_per_call = 50
if len(sys.argv) > 1:
file = open(sys.argv[1])
else:
file = sys.stdin
tids = file.read().split()

client_credentials_manager = SpotifyClientCredentials()
sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager)
for start in range(0, len(tids), max_tracks_per_call):
results = sp.tracks(tids[start: start + max_tracks_per_call])
for track in results['tracks']:
print(track['name'] + ' - ' + track['artists'][0]['name'])
def main():
args = get_args()
sp = spotipy.Spotify(auth_manager=SpotifyOAuth())
track_list = sp.tracks(args.uris)
for track in track_list['tracks']:
print(track['name'] + ' - ' + track['artists'][0]['name'])


if __name__ == '__main__':
main()
11 changes: 0 additions & 11 deletions examples/test.py

This file was deleted.

6 changes: 4 additions & 2 deletions examples/unfollow_playlist.py
Original file line number Diff line number Diff line change
@@ -4,6 +4,8 @@
import spotipy
from spotipy.oauth2 import SpotifyOAuth

scope = 'playlist-modify-public'

logger = logging.getLogger('examples.unfollow_playlist')
logging.basicConfig(level='DEBUG')

@@ -23,9 +25,9 @@ def get_args():

def main():
args = get_args()
sp = spotipy.Spotify(auth_manager=SpotifyOAuth())
sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope))
sp.current_user_unfollow_playlist(args.playlist)


if __name__ == '__main__':
main()
main()
Loading

0 comments on commit 7fc5ea8

Please sign in to comment.