From 2b6ca84b688ca96881b1a16a6af9ec391fac3e9b Mon Sep 17 00:00:00 2001 From: haviv1idan Date: Mon, 11 Nov 2024 18:18:38 +0000 Subject: [PATCH 1/3] replacing %s with f-string --- examples/artist_albums.py | 9 ++-- examples/artist_discography.py | 17 ++++---- examples/artist_recommendations.py | 8 +--- examples/audio_analysis_for_track.py | 5 +-- examples/audio_features.py | 5 +-- examples/follow_playlist.py | 11 +---- examples/my_playlists.py | 2 +- examples/show_my_saved_tracks.py | 3 +- examples/user_playlists_contents.py | 4 +- examples/user_public_playlists.py | 14 ++----- spotipy/cache_handler.py | 8 ++-- spotipy/client.py | 12 +++--- spotipy/oauth2.py | 52 +++++++++++------------- spotipy/util.py | 1 + tests/integration/user_endpoints/test.py | 4 +- 15 files changed, 59 insertions(+), 96 deletions(-) diff --git a/examples/artist_albums.py b/examples/artist_albums.py index c5cc7a6a..ce89b6eb 100644 --- a/examples/artist_albums.py +++ b/examples/artist_albums.py @@ -20,10 +20,7 @@ def get_args(): def get_artist(name): results = sp.search(q='artist:' + name, type='artist') items = results['artists']['items'] - if len(items) > 0: - return items[0] - else: - return None + return items[0] if items else None def show_artist_albums(artist): @@ -38,7 +35,7 @@ def show_artist_albums(artist): for album in albums: name = album['name'] if name not in seen: - logger.info('ALBUM: %s', name) + logger.info(f'ALBUM: {name}') seen.add(name) @@ -48,7 +45,7 @@ def main(): if artist: show_artist_albums(artist) else: - logger.error("Can't find artist: %s", artist) + logger.error(f"Can't find artist: {artist}") if __name__ == '__main__': diff --git a/examples/artist_discography.py b/examples/artist_discography.py index 84f9c268..95455d3f 100644 --- a/examples/artist_discography.py +++ b/examples/artist_discography.py @@ -20,10 +20,7 @@ def get_args(): def get_artist(name): results = sp.search(q='artist:' + name, type='artist') items = results['artists']['items'] - if len(items) > 0: - return items[0] - else: - return None + return items[0] if items else None def show_album_tracks(album): @@ -34,7 +31,7 @@ def show_album_tracks(album): results = sp.next(results) tracks.extend(results['items']) for i, track in enumerate(tracks): - logger.info('%s. %s', i + 1, track['name']) + logger.info(f"{i + 1}. {track['name']}") def show_artist_albums(artist): @@ -44,21 +41,21 @@ def show_artist_albums(artist): while results['next']: results = sp.next(results) albums.extend(results['items']) - logger.info('Total albums: %s', len(albums)) + logger.info(f'Total albums: {len(album)}') unique = set() # skip duplicate albums for album in albums: name = album['name'].lower() if name not in unique: - logger.info('ALBUM: %s', name) + logger.info(f"ALBUM: {name}") unique.add(name) show_album_tracks(album) def show_artist(artist): - logger.info('====%s====', artist['name']) - logger.info('Popularity: %s', artist['popularity']) + logger.info(artist['name'].center(10, '=')) + logger.info(f'Popularity: {artist['popularity']}') if len(artist['genres']) > 0: - logger.info('Genres: %s', ','.join(artist['genres'])) + logger.info(f"Genres: {','.join(artist['genres'])}") def main(): diff --git a/examples/artist_recommendations.py b/examples/artist_recommendations.py index 40a95a23..fdcdda14 100644 --- a/examples/artist_recommendations.py +++ b/examples/artist_recommendations.py @@ -22,17 +22,13 @@ def get_args(): def get_artist(name): results = sp.search(q='artist:' + name, type='artist') items = results['artists']['items'] - if len(items) > 0: - return items[0] - else: - return None + return items[0] if items else None def show_recommendations_for_artist(artist): results = sp.recommendations(seed_artists=[artist['id']]) for track in results['tracks']: - logger.info('Recommendation: %s - %s', track['name'], - track['artists'][0]['name']) + logger.info(f"Recommendation: {track['name']} - {track['artists'][0]['name']}") def main(): diff --git a/examples/audio_analysis_for_track.py b/examples/audio_analysis_for_track.py index 1bef5e9f..d4d5e88b 100644 --- a/examples/audio_analysis_for_track.py +++ b/examples/audio_analysis_for_track.py @@ -10,10 +10,7 @@ client_credentials_manager = SpotifyClientCredentials() sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) -if len(sys.argv) > 1: - tid = sys.argv[1] -else: - tid = 'spotify:track:4TTV7EcfroSLWzXRY6gLv6' +tid = sys.argv[1] if len(sys.argv) > 1 else 'spotify:track:4TTV7EcfroSLWzXRY6gLv6' start = time.time() analysis = sp.audio_analysis(tid) diff --git a/examples/audio_features.py b/examples/audio_features.py index 4657a972..e51f588d 100644 --- a/examples/audio_features.py +++ b/examples/audio_features.py @@ -11,10 +11,7 @@ sp = spotipy.Spotify(client_credentials_manager=client_credentials_manager) sp.trace = False -if len(sys.argv) > 1: - artist_name = ' '.join(sys.argv[1:]) -else: - artist_name = 'weezer' +artist_name = ' '.join(sys.argv[1:]) if len(sys.argv) > 1 else 'weezer' results = sp.search(q=artist_name, limit=50) tids = [] diff --git a/examples/follow_playlist.py b/examples/follow_playlist.py index 6973468c..9a271bef 100644 --- a/examples/follow_playlist.py +++ b/examples/follow_playlist.py @@ -13,15 +13,8 @@ def get_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) - + playlist = args.playlist or '37i9dQZEVXbMDoHDwVN2tF' # default is Spotify Global Top 50 playlist + spotipy.Spotify(auth_manager=SpotifyOAuth()).current_user_follow_playlist(playlist) if __name__ == '__main__': main() diff --git a/examples/my_playlists.py b/examples/my_playlists.py index 8c8e9be1..5588e7e0 100644 --- a/examples/my_playlists.py +++ b/examples/my_playlists.py @@ -8,4 +8,4 @@ results = sp.current_user_playlists(limit=50) for i, item in enumerate(results['items']): - print("%d %s" % (i, item['name'])) + print(f"{i}, {item['name']}") diff --git a/examples/show_my_saved_tracks.py b/examples/show_my_saved_tracks.py index ebff4fea..574dff1d 100644 --- a/examples/show_my_saved_tracks.py +++ b/examples/show_my_saved_tracks.py @@ -9,8 +9,7 @@ def show_tracks(results): for item in results['items']: track = item['track'] - print("%32.32s %s" % (track['artists'][0]['name'], track['name'])) - + print(f"{track['artists'][0]['name']:<32.32} {track['name']}") sp = spotipy.Spotify(auth_manager=SpotifyOAuth(scope=scope)) diff --git a/examples/user_playlists_contents.py b/examples/user_playlists_contents.py index 9379a0b8..9973859f 100644 --- a/examples/user_playlists_contents.py +++ b/examples/user_playlists_contents.py @@ -7,9 +7,7 @@ def show_tracks(results): for i, item in enumerate(results['items']): track = item['track'] - print( - " %d %32.32s %s" % - (i, track['artists'][0]['name'], track['name'])) + print(f"{i:2d} {track['artists'][0]['name']:<32.32} {track['name']}") if __name__ == '__main__': diff --git a/examples/user_public_playlists.py b/examples/user_public_playlists.py index 2d7f64f2..727ab5b8 100644 --- a/examples/user_public_playlists.py +++ b/examples/user_public_playlists.py @@ -18,14 +18,6 @@ while playlists: for i, playlist in enumerate(playlists['items']): - print( - "%4d %s %s" % - (i + - 1 + - playlists['offset'], - playlist['uri'], - playlist['name'])) - if playlists['next']: - playlists = sp.next(playlists) - else: - playlists = None + print(f"{i + 1 + playlists['offset']:4d} {playlist['uri']} {playlist['name']}") + + playlists = sp.next(playlists) if playlists['next'] else None diff --git a/spotipy/cache_handler.py b/spotipy/cache_handler.py index 7ae94a23..fdf9d1d9 100644 --- a/spotipy/cache_handler.py +++ b/spotipy/cache_handler.py @@ -83,9 +83,9 @@ def get_cached_token(self): except OSError as error: if error.errno == errno.ENOENT: - logger.debug("cache does not exist at: %s", self.cache_path) + logger.debug(f"cache does not exist at: {self.cache_path}") else: - logger.warning("Couldn't read cache at: %s", self.cache_path) + logger.warning(f"Couldn't read cache at: {self.cache_path}") return token_info @@ -95,8 +95,7 @@ def save_token_to_cache(self, token_info): f.write(json.dumps(token_info, cls=self.encoder_cls)) f.close() except OSError: - logger.warning('Couldn\'t write token to cache at: %s', - self.cache_path) + logger.warning(f"Couldn\'t write token to cache at: {self.cache_path}") class MemoryCacheHandler(CacheHandler): @@ -214,6 +213,7 @@ def save_token_to_cache(self, token_info): class MemcacheCacheHandler(CacheHandler): """A Cache handler that stores the token info in Memcache using the pymemcache client """ + def __init__(self, memcache, key=None) -> None: """ Parameters: diff --git a/spotipy/client.py b/spotipy/client.py index 61924a55..2ff7621d 100644 --- a/spotipy/client.py +++ b/spotipy/client.py @@ -263,8 +263,9 @@ def _internal_call(self, method, url, payload, params): if self.language is not None: headers["Accept-Language"] = self.language - logger.debug('Sending %s to %s with Params: %s Headers: %s and Body: %r ', - method, url, args.get("params"), headers, args.get('data')) + logger.debug( + f"Sending {method} to {url} with Params: {args.get('params')} \ + Headers: {headers} and Body: {args.get('data')!r}") try: response = self._session.request( @@ -290,9 +291,8 @@ def _internal_call(self, method, url, payload, params): reason = None logger.error( - 'HTTP Error for %s to %s with Params: %s returned %s due to %s', - method, url, args.get("params"), response.status_code, msg - ) + f'HTTP Error for {method} to {url} with Params: {args.get("params")} \ + returned {response.status_code} due to {msg}') raise SpotifyException( response.status_code, @@ -317,7 +317,7 @@ def _internal_call(self, method, url, payload, params): except ValueError: results = None - logger.debug('RESULTS: %s', results) + logger.debug(f'RESULTS: {results}') return results def _get(self, url, args=None, payload=None, **kwargs): diff --git a/spotipy/oauth2.py b/spotipy/oauth2.py index 1591e77d..afb7cc19 100644 --- a/spotipy/oauth2.py +++ b/spotipy/oauth2.py @@ -218,8 +218,8 @@ def _request_access_token(self): ) logger.debug( - "sending POST request to %s with Headers: %s and Body: %r", - self.OAUTH_TOKEN_URL, headers, payload + f"Sending POST request to {self.OAUTH_TOKEN_URL} \ + with Headers: {headers} and Body: {payload!r}" ) try: @@ -401,9 +401,9 @@ def _open_auth_url(self): auth_url = self.get_authorize_url() try: webbrowser.open(auth_url) - logger.info("Opened %s in your browser", auth_url) + logger.info(f"Opened {auth_url} in your browser") except webbrowser.Error: - logger.error("Please navigate here: %s", auth_url) + logger.error(f"Please navigate here: {auth_url}") def _get_auth_response_interactive(self, open_browser=False): if open_browser: @@ -411,10 +411,8 @@ def _get_auth_response_interactive(self, open_browser=False): prompt = "Enter the URL you were redirected to: " else: url = self.get_authorize_url() - prompt = ( - "Go to the following URL: {}\n" - "Enter the URL you were redirected to: ".format(url) - ) + prompt = (f"Go to the following URL: {url}\nEnter the URL you were redirected to: ") + response = self._get_user_input(prompt) state, code = SpotifyOAuth.parse_auth_response_url(response) if self.state is not None and self.state != state: @@ -457,12 +455,11 @@ def get_auth_response(self, open_browser=None): if redirect_port: return self._get_auth_response_local_server(redirect_port) else: - logger.warning('Using `%s` as redirect URI without a port. ' - 'Specify a port (e.g. `%s:8080`) to allow ' + logger.warning(f'Using `{redirect_host}` as redirect URI without a port. ' + f'Specify a port (e.g. `{redirect_host}:8080`) to allow ' 'automatic retrieval of authentication code ' 'instead of having to copy and paste ' - 'the URL your browser is redirected to.', - redirect_host, redirect_host) + 'the URL your browser is redirected to.') return self._get_auth_response_interactive(open_browser=open_browser) @@ -511,8 +508,8 @@ def get_access_token(self, code=None, as_dict=True, check_cache=True): headers = self._make_authorization_headers() logger.debug( - "sending POST request to %s with Headers: %s and Body: %r", - self.OAUTH_TOKEN_URL, headers, payload + f"Sending POST request to {self.OAUTH_TOKEN_URL} \ + with Headers: {headers} and Body: {payload!r}" ) try: @@ -541,8 +538,8 @@ def refresh_access_token(self, refresh_token): headers = self._make_authorization_headers() logger.debug( - "sending POST request to %s with Headers: %s and Body: %r", - self.OAUTH_TOKEN_URL, headers, payload + f"Sending POST request to {self.OAUTH_TOKEN_URL} \ + with Headers: {headers} and Body: {payload!r}" ) try: @@ -733,9 +730,9 @@ def _open_auth_url(self, state=None): auth_url = self.get_authorize_url(state) try: webbrowser.open(auth_url) - logger.info("Opened %s in your browser", auth_url) + logger.info(f"Opened {auth_url} in your browser") except webbrowser.Error: - logger.error("Please navigate here: %s", auth_url) + logger.error(f"Please navigate here: {auth_url}") def _get_auth_response(self, open_browser=None): logger.info('User authentication requires interaction with your ' @@ -759,12 +756,11 @@ def _get_auth_response(self, open_browser=None): if redirect_port: return self._get_auth_response_local_server(redirect_port) else: - logger.warning('Using `%s` as redirect URI without a port. ' - 'Specify a port (e.g. `%s:8080`) to allow ' + logger.warning(f'Using `{redirect_host}` as redirect URI without a port. ' + f'Specify a port (e.g. `{redirect_host}:8080`) to allow ' 'automatic retrieval of authentication code ' 'instead of having to copy and paste ' - 'the URL your browser is redirected to.', - redirect_host, redirect_host) + 'the URL your browser is redirected to.') return self._get_auth_response_interactive(open_browser=open_browser) def _get_auth_response_local_server(self, redirect_port): @@ -868,8 +864,8 @@ def get_access_token(self, code=None, check_cache=True): headers = {"Content-Type": "application/x-www-form-urlencoded"} logger.debug( - "sending POST request to %s with Headers: %s and Body: %r", - self.OAUTH_TOKEN_URL, headers, payload + f"Sending POST request to {self.OAUTH_TOKEN_URL} \ + with Headers: {headers} and Body: {payload!r}" ) try: @@ -899,8 +895,8 @@ def refresh_access_token(self, refresh_token): headers = {"Content-Type": "application/x-www-form-urlencoded"} logger.debug( - "sending POST request to %s with Headers: %s and Body: %r", - self.OAUTH_TOKEN_URL, headers, payload + f"Sending POST request to {self.OAUTH_TOKEN_URL} \ + with Headers: {headers} and Body: {payload!r}" ) try: @@ -1152,9 +1148,9 @@ def _open_auth_url(self, state=None): auth_url = self.get_authorize_url(state) try: webbrowser.open(auth_url) - logger.info("Opened %s in your browser", auth_url) + logger.info(f"Opened {auth_url} in your browser") except webbrowser.Error: - logger.error("Please navigate here: %s", auth_url) + logger.error(f"Please navigate here: {auth_url}") def get_auth_response(self, state=None): """ Gets a new auth **token** with user interaction """ diff --git a/spotipy/util.py b/spotipy/util.py index 2d9e012d..0503e809 100644 --- a/spotipy/util.py +++ b/spotipy/util.py @@ -153,6 +153,7 @@ class Retry(urllib3.Retry): """ Custom class for printing a warning when a rate/request limit is reached. """ + def increment( self, method: str | None = None, diff --git a/tests/integration/user_endpoints/test.py b/tests/integration/user_endpoints/test.py index fb1fbb21..030f0922 100644 --- a/tests/integration/user_endpoints/test.py +++ b/tests/integration/user_endpoints/test.py @@ -586,7 +586,7 @@ def test_add_to_queue(self, mock_post): self.spotify.add_to_queue(test_uri) # Check if the correct endpoint is called - endpoint = "me/player/queue?uri=%s" % test_uri + endpoint = f"me/player/queue?uri={test_uri}" mock_post.assert_called_with(endpoint) def test_add_to_queue_with_device_id(self, mock_post): @@ -597,5 +597,5 @@ def test_add_to_queue_with_device_id(self, mock_post): self.spotify.add_to_queue(test_uri, device_id=device_id) # Check if the correct endpoint is called - endpoint = "me/player/queue?uri=%s&device_id=%s" % (test_uri, device_id) + endpoint = f"me/player/queue?uri={test_uri}&device_id={device_id}" mock_post.assert_called_with(endpoint) From 1793819eef8d313828b9023c0ac3a50a8545ed6d Mon Sep 17 00:00:00 2001 From: haviv1idan Date: Mon, 11 Nov 2024 18:42:18 +0000 Subject: [PATCH 2/3] update CHANGELOG.md and update setup.py version --- CHANGELOG.md | 5 +++++ setup.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 86ebb8b9..606344fa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -28,6 +28,11 @@ Add your changes below. ### Removed - `mock` no longer listed as a test dependency. Only built-in `unittest.mock` is actually used. +## [2.24.1] - 2024-11-11 + +### Changed +- replaced %s strings with f-strings + ## [2.24.0] - 2024-05-30 ### Added diff --git a/setup.py b/setup.py index be5a982c..6cc2f251 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name='spotipy', - version='2.24.0', + version='2.24.1', description='A light weight Python library for the Spotify Web API', long_description=long_description, long_description_content_type="text/markdown", From 67f23885aa6aa6bb74f34d884969c43a7bc1e67b Mon Sep 17 00:00:00 2001 From: Niko Date: Mon, 25 Nov 2024 11:50:20 +0100 Subject: [PATCH 3/3] please do not change the version number --- CHANGELOG.md | 6 +----- setup.py | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 606344fa..0bad66bf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,15 +24,11 @@ Add your changes below. - Audiobook integration tests - Edited docstrings for certain functions in client.py for functions that are no longer in use and have been replaced. - `current_user_unfollow_playlist()` now supports playlist IDs, URLs, and URIs rather than previously where it only supported playlist IDs. +- replaced %s strings with f-strings ### Removed - `mock` no longer listed as a test dependency. Only built-in `unittest.mock` is actually used. -## [2.24.1] - 2024-11-11 - -### Changed -- replaced %s strings with f-strings - ## [2.24.0] - 2024-05-30 ### Added diff --git a/setup.py b/setup.py index 6cc2f251..be5a982c 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name='spotipy', - version='2.24.1', + version='2.24.0', description='A light weight Python library for the Spotify Web API', long_description=long_description, long_description_content_type="text/markdown",