diff --git a/spotdl/downloader.py b/spotdl/downloader.py index 608a5c3..43cb668 100644 --- a/spotdl/downloader.py +++ b/spotdl/downloader.py @@ -28,8 +28,7 @@ class CheckExists: for song in songs: # check if a song with the same name is already present in the given folder if self._match_filenames(song): - if internals.is_spotify(raw_song) and \ - not self._has_metadata(song): + if internals.is_spotify(raw_song) and not self._has_metadata(song): return False log.warning('"{}" already exists'.format(song)) @@ -53,9 +52,7 @@ class CheckExists: already_tagged = metadata.compare( os.path.join(const.args.folder, song), self.meta_tags ) - log.debug( - "Checking if it is already tagged correctly? {}", already_tagged - ) + log.debug("Checking if it is already tagged correctly? {}", already_tagged) if not already_tagged: os.remove(os.path.join(const.args.folder, song)) return False @@ -64,8 +61,7 @@ class CheckExists: def _prompt_song(self, song): log.info( - '"{}" has already been downloaded. ' - "Re-download? (y/N): ".format(song) + '"{}" has already been downloaded. ' "Re-download? (y/N): ".format(song) ) prompt = input("> ") if prompt.lower() == "y": diff --git a/spotdl/handle.py b/spotdl/handle.py index e158703..54a7a49 100644 --- a/spotdl/handle.py +++ b/spotdl/handle.py @@ -99,10 +99,7 @@ def get_arguments(raw_args=None, to_group=True, to_merge=True): group = parser.add_mutually_exclusive_group(required=True) group.add_argument( - "-s", - "--song", - nargs='+', - help="download track by spotify link or name" + "-s", "--song", nargs="+", help="download track by spotify link or name" ) group.add_argument("-l", "--list", help="download tracks from a file") group.add_argument( @@ -116,7 +113,7 @@ def get_arguments(raw_args=None, to_group=True, to_merge=True): group.add_argument( "-ab", "--all-albums", - help="load all tracks from artist URL into .txt" + help="load all tracks from artist URL into .txt", ) group.add_argument( "-u", @@ -128,10 +125,10 @@ def get_arguments(raw_args=None, to_group=True, to_merge=True): ) parser.add_argument( - '--write-m3u', + "--write-m3u", help="generate an .m3u playlist file with youtube links given " - "a text file containing tracks", - action='store_true' + "a text file containing tracks", + action="store_true", ) parser.add_argument( "-m", @@ -266,12 +263,19 @@ def get_arguments(raw_args=None, to_group=True, to_merge=True): if parsed.config is not None and to_merge: parsed = override_config(parsed.config, parser) - if to_group and parsed.list and \ - not mimetypes.MimeTypes().guess_type(parsed.list)[0] == "text/plain": - parser.error("{0} is not of a valid argument to --list, argument must be plain text file".format(parsed.list)) + if ( + to_group + and parsed.list + and not mimetypes.MimeTypes().guess_type(parsed.list)[0] == "text/plain" + ): + parser.error( + "{0} is not of a valid argument to --list, argument must be plain text file".format( + parsed.list + ) + ) if parsed.write_m3u and not parsed.list: - parser.error('--write-m3u can only be used with --list') + parser.error("--write-m3u can only be used with --list") parsed.log_level = log_leveller(parsed.log_level) diff --git a/spotdl/spotify_tools.py b/spotdl/spotify_tools.py index 354588d..d26855d 100644 --- a/spotdl/spotify_tools.py +++ b/spotdl/spotify_tools.py @@ -27,6 +27,7 @@ def refresh_token(): new_token = generate_token() spotify = spotipy.Spotify(auth=new_token) + # token is mandatory when using Spotify's API # https://developer.spotify.com/news-stories/2017/01/27/removing-unauthenticated-calls-to-the-web-api/ _token = generate_token() diff --git a/spotdl/youtube_tools.py b/spotdl/youtube_tools.py index 1cb4192..9c1705f 100644 --- a/spotdl/youtube_tools.py +++ b/spotdl/youtube_tools.py @@ -53,7 +53,7 @@ def match_video_and_metadata(track, force_pafy=True): # Let it generate metadata, youtube doesn't know spotify slang if not const.args.no_metadata or internals.is_spotify(track): meta_tags = spotify_tools.generate_metadata(track) - + if force_pafy: content = go_pafy(track, meta_tags) else: diff --git a/test/test_download_with_metadata.py b/test/test_download_with_metadata.py index a5ab54e..8573c1d 100644 --- a/test/test_download_with_metadata.py +++ b/test/test_download_with_metadata.py @@ -60,13 +60,21 @@ def monkeypatch_youtube_search_page(*args, **kwargs): def test_youtube_url(metadata_fixture, monkeypatch): - monkeypatch.setattr(youtube_tools.GenerateYouTubeURL, "_fetch_response", monkeypatch_youtube_search_page) + monkeypatch.setattr( + youtube_tools.GenerateYouTubeURL, + "_fetch_response", + monkeypatch_youtube_search_page, + ) url = youtube_tools.generate_youtube_url(SPOTIFY_TRACK_URL, metadata_fixture) assert url == EXPECTED_YOUTUBE_URL def test_youtube_title(metadata_fixture, monkeypatch): - monkeypatch.setattr(youtube_tools.GenerateYouTubeURL, "_fetch_response", monkeypatch_youtube_search_page) + monkeypatch.setattr( + youtube_tools.GenerateYouTubeURL, + "_fetch_response", + monkeypatch_youtube_search_page, + ) content = youtube_tools.go_pafy(SPOTIFY_TRACK_URL, metadata_fixture) pytest.content_fixture = content title = youtube_tools.get_youtube_title(content) @@ -99,61 +107,84 @@ class TestDownload: def test_m4a(self, monkeypatch, filename_fixture): expect_download = True - monkeypatch.setattr("pafy.backend_shared.BaseStream.download", self.blank_audio_generator) - download = youtube_tools.download_song(filename_fixture + ".m4a", pytest.content_fixture) + monkeypatch.setattr( + "pafy.backend_shared.BaseStream.download", self.blank_audio_generator + ) + download = youtube_tools.download_song( + filename_fixture + ".m4a", pytest.content_fixture + ) assert download == expect_download def test_webm(self, monkeypatch, filename_fixture): expect_download = True - monkeypatch.setattr("pafy.backend_shared.BaseStream.download", self.blank_audio_generator) - download = youtube_tools.download_song(filename_fixture + ".webm", pytest.content_fixture) + monkeypatch.setattr( + "pafy.backend_shared.BaseStream.download", self.blank_audio_generator + ) + download = youtube_tools.download_song( + filename_fixture + ".webm", pytest.content_fixture + ) assert download == expect_download class TestFFmpeg: def test_convert_from_webm_to_mp3(self, filename_fixture, monkeypatch): - expect_command = "ffmpeg -y -i {0}.webm -codec:a libmp3lame -ar 44100 -b:a 192k -vn {0}.mp3".format(os.path.join(const.args.folder, filename_fixture)) + expect_command = "ffmpeg -y -i {0}.webm -codec:a libmp3lame -ar 44100 -b:a 192k -vn {0}.mp3".format( + os.path.join(const.args.folder, filename_fixture) + ) _, command = convert.song( filename_fixture + ".webm", filename_fixture + ".mp3", const.args.folder ) - assert ' '.join(command) == expect_command + assert " ".join(command) == expect_command def test_convert_from_webm_to_m4a(self, filename_fixture, monkeypatch): - expect_command = "ffmpeg -y -i {0}.webm -cutoff 20000 -codec:a aac -ar 44100 -b:a 192k -vn {0}.m4a".format(os.path.join(const.args.folder, filename_fixture)) + expect_command = "ffmpeg -y -i {0}.webm -cutoff 20000 -codec:a aac -ar 44100 -b:a 192k -vn {0}.m4a".format( + os.path.join(const.args.folder, filename_fixture) + ) _, command = convert.song( filename_fixture + ".webm", filename_fixture + ".m4a", const.args.folder ) - assert ' '.join(command) == expect_command + assert " ".join(command) == expect_command def test_convert_from_m4a_to_mp3(self, filename_fixture, monkeypatch): - expect_command = "ffmpeg -y -i {0}.m4a -codec:v copy -codec:a libmp3lame -ar 44100 -b:a 192k -vn {0}.mp3".format(os.path.join(const.args.folder, filename_fixture)) + expect_command = "ffmpeg -y -i {0}.m4a -codec:v copy -codec:a libmp3lame -ar 44100 -b:a 192k -vn {0}.mp3".format( + os.path.join(const.args.folder, filename_fixture) + ) _, command = convert.song( filename_fixture + ".m4a", filename_fixture + ".mp3", const.args.folder ) - assert ' '.join(command) == expect_command + assert " ".join(command) == expect_command def test_convert_from_m4a_to_webm(self, filename_fixture, monkeypatch): - expect_command = "ffmpeg -y -i {0}.m4a -codec:a libopus -vbr on -b:a 192k -vn {0}.webm".format(os.path.join(const.args.folder, filename_fixture)) + expect_command = "ffmpeg -y -i {0}.m4a -codec:a libopus -vbr on -b:a 192k -vn {0}.webm".format( + os.path.join(const.args.folder, filename_fixture) + ) _, command = convert.song( filename_fixture + ".m4a", filename_fixture + ".webm", const.args.folder ) - assert ' '.join(command) == expect_command + assert " ".join(command) == expect_command def test_convert_from_m4a_to_flac(self, filename_fixture, monkeypatch): - expect_command = "ffmpeg -y -i {0}.m4a -codec:a flac -ar 44100 -b:a 192k -vn {0}.flac".format(os.path.join(const.args.folder, filename_fixture)) + expect_command = "ffmpeg -y -i {0}.m4a -codec:a flac -ar 44100 -b:a 192k -vn {0}.flac".format( + os.path.join(const.args.folder, filename_fixture) + ) _, command = convert.song( filename_fixture + ".m4a", filename_fixture + ".flac", const.args.folder ) - assert ' '.join(command) == expect_command + assert " ".join(command) == expect_command class TestAvconv: def test_convert_from_m4a_to_mp3(self, filename_fixture): - expect_command = "avconv -loglevel debug -i {0}.m4a -ab 192k {0}.mp3 -y".format(os.path.join(const.args.folder, filename_fixture)) - _, command = convert.song( - filename_fixture + ".m4a", filename_fixture + ".mp3", const.args.folder, avconv=True + expect_command = "avconv -loglevel debug -i {0}.m4a -ab 192k {0}.mp3 -y".format( + os.path.join(const.args.folder, filename_fixture) ) - assert ' '.join(command) == expect_command + _, command = convert.song( + filename_fixture + ".m4a", + filename_fixture + ".mp3", + const.args.folder, + avconv=True, + ) + assert " ".join(command) == expect_command @pytest.fixture(scope="module") @@ -187,7 +218,9 @@ class TestEmbedMetadata: assert embed == expect_embed -def test_check_track_exists_after_download(metadata_fixture, filename_fixture, trackpath_fixture): +def test_check_track_exists_after_download( + metadata_fixture, filename_fixture, trackpath_fixture +): expect_check = True track_existence = downloader.CheckExists(filename_fixture, metadata_fixture) check = track_existence.already_exists(SPOTIFY_TRACK_URL) diff --git a/test/test_handle.py b/test/test_handle.py index 4cef0a5..e93b31d 100644 --- a/test/test_handle.py +++ b/test/test_handle.py @@ -10,13 +10,11 @@ import yaml def test_error_m3u_without_list(): with pytest.raises(SystemExit): - handle.get_arguments(raw_args=('-s cool song', '--write-m3u',), - to_group=True) + handle.get_arguments(raw_args=("-s cool song", "--write-m3u"), to_group=True) def test_m3u_with_list(): - handle.get_arguments(raw_args=('-l cool_list.txt', '--write-m3u',), - to_group=True) + handle.get_arguments(raw_args=("-l cool_list.txt", "--write-m3u"), to_group=True) def test_log_str_to_int(): @@ -27,8 +25,7 @@ def test_log_str_to_int(): @pytest.fixture(scope="module") def config_path_fixture(tmpdir_factory): - config_path = os.path.join(str(tmpdir_factory.mktemp("config")), - "config.yml") + config_path = os.path.join(str(tmpdir_factory.mktemp("config")), "config.yml") return config_path @@ -53,9 +50,12 @@ class TestConfig: parser = argparse.ArgumentParser() with open(config_path_fixture, "w") as config_file: yaml.dump(modified_config_fixture, config_file, default_flow_style=False) - overridden_config = handle.override_config(config_path_fixture, parser, raw_args="") + overridden_config = handle.override_config( + config_path_fixture, parser, raw_args="" + ) modified_values = [ - str(value) for value in modified_config_fixture["spotify-downloader"].values() + str(value) + for value in modified_config_fixture["spotify-downloader"].values() ] overridden_config.folder = os.path.realpath(overridden_config.folder) overridden_values = [ diff --git a/test/test_internals.py b/test/test_internals.py index e2a8875..7bcaf3b 100644 --- a/test/test_internals.py +++ b/test/test_internals.py @@ -86,7 +86,7 @@ FROM_SECONDS_TEST_TABLE = [ (158, "2:38"), (263, "4:23"), (4562, "1:16:02"), - (26762, "7:26:02") + (26762, "7:26:02"), ] @@ -114,8 +114,7 @@ def test_default_music_directory(): @pytest.fixture(scope="module") def directory_fixture(tmpdir_factory): - dir_path = os.path.join(str(tmpdir_factory.mktemp("tmpdir")), - "filter_this_folder") + dir_path = os.path.join(str(tmpdir_factory.mktemp("tmpdir")), "filter_this_folder") return dir_path diff --git a/test/test_spotify_tools.py b/test/test_spotify_tools.py index 5a26dd9..671f752 100644 --- a/test/test_spotify_tools.py +++ b/test/test_spotify_tools.py @@ -36,12 +36,16 @@ class TestGenerateMetadata: def test_get_playlists(): - expect_playlist_ids = [ "34gWCK8gVeYDPKcctB6BQJ", - "04wTU2c2WNQG9XE5oSLYfj", - "0fWBMhGh38y0wsYWwmM9Kt" ] + expect_playlist_ids = [ + "34gWCK8gVeYDPKcctB6BQJ", + "04wTU2c2WNQG9XE5oSLYfj", + "0fWBMhGh38y0wsYWwmM9Kt", + ] - expect_playlists = [ "https://open.spotify.com/playlist/" + playlist_id - for playlist_id in expect_playlist_ids ] + expect_playlists = [ + "https://open.spotify.com/playlist/" + playlist_id + for playlist_id in expect_playlist_ids + ] playlists = spotify_tools.get_playlists("uqlakumu7wslkoen46s5bulq0") assert playlists == expect_playlists @@ -60,7 +64,9 @@ def test_write_user_playlist(tmpdir, monkeypatch): class TestFetchPlaylist: @pytest.fixture(scope="module") def playlist_fixture(self): - playlist = spotify_tools.fetch_playlist("https://open.spotify.com/playlist/0fWBMhGh38y0wsYWwmM9Kt") + playlist = spotify_tools.fetch_playlist( + "https://open.spotify.com/playlist/0fWBMhGh38y0wsYWwmM9Kt" + ) return playlist def test_name(self, playlist_fixture): @@ -73,7 +79,9 @@ class TestFetchPlaylist: def test_write_playlist(tmpdir): expect_tracks = 14 text_file = os.path.join(str(tmpdir), "test_pl.txt") - spotify_tools.write_playlist("https://open.spotify.com/playlist/0fWBMhGh38y0wsYWwmM9Kt", text_file) + spotify_tools.write_playlist( + "https://open.spotify.com/playlist/0fWBMhGh38y0wsYWwmM9Kt", text_file + ) with open(text_file, "r") as f: tracks = len(f.readlines()) assert tracks == expect_tracks @@ -83,7 +91,9 @@ def test_write_playlist(tmpdir): class TestFetchAlbum: @pytest.fixture(scope="module") def album_fixture(self): - album = spotify_tools.fetch_album("https://open.spotify.com/album/499J8bIsEnU7DSrosFDJJg") + album = spotify_tools.fetch_album( + "https://open.spotify.com/album/499J8bIsEnU7DSrosFDJJg" + ) return album def test_name(self, album_fixture): @@ -97,7 +107,9 @@ class TestFetchAlbum: class TestFetchAlbumsFromArtist: @pytest.fixture(scope="module") def albums_from_artist_fixture(self): - albums = spotify_tools.fetch_albums_from_artist("https://open.spotify.com/artist/7oPftvlwr6VrsViSDV7fJY") + albums = spotify_tools.fetch_albums_from_artist( + "https://open.spotify.com/artist/7oPftvlwr6VrsViSDV7fJY" + ) return albums def test_len(self, albums_from_artist_fixture): @@ -122,7 +134,9 @@ def test_write_all_albums_from_artist(tmpdir): # in US market only expect_tracks = 49 text_file = os.path.join(str(tmpdir), "test_ab.txt") - spotify_tools.write_all_albums_from_artist("https://open.spotify.com/artist/4dpARuHxo51G3z768sgnrY", text_file) + spotify_tools.write_all_albums_from_artist( + "https://open.spotify.com/artist/4dpARuHxo51G3z768sgnrY", text_file + ) with open(text_file, "r") as f: tracks = len(f.readlines()) assert tracks == expect_tracks @@ -131,7 +145,9 @@ def test_write_all_albums_from_artist(tmpdir): def test_write_album(tmpdir): expect_tracks = 15 text_file = os.path.join(str(tmpdir), "test_al.txt") - spotify_tools.write_album("https://open.spotify.com/album/499J8bIsEnU7DSrosFDJJg", text_file) + spotify_tools.write_album( + "https://open.spotify.com/album/499J8bIsEnU7DSrosFDJJg", text_file + ) with open(text_file, "r") as f: tracks = len(f.readlines()) assert tracks == expect_tracks diff --git a/test/test_youtube_tools.py b/test/test_youtube_tools.py index 45867c4..eb5393c 100644 --- a/test/test_youtube_tools.py +++ b/test/test_youtube_tools.py @@ -111,7 +111,9 @@ class TestYouTubeTitle: youtube_tools.set_api_key() assert title_fixture == EXPECTED_TITLE - def test_download_from_list_without_youtube_api(self, metadata_fixture, content_fixture): + def test_download_from_list_without_youtube_api( + self, metadata_fixture, content_fixture + ): const.args.youtube_api_key = None youtube_tools.set_api_key() content_fixture = youtube_tools.go_pafy(TRACK_SEARCH, metadata_fixture) @@ -139,11 +141,15 @@ class TestDownload: # content_fixture does not have any .webm audiostream expect_download = False monkeypatch.setattr("pafy.backend_shared.BaseStream.download", lambda x: None) - download = youtube_tools.download_song(filename_fixture + ".webm", content_fixture) + download = youtube_tools.download_song( + filename_fixture + ".webm", content_fixture + ) assert download == expect_download def test_other(self, content_fixture, filename_fixture, monkeypatch): expect_download = False monkeypatch.setattr("pafy.backend_shared.BaseStream.download", lambda x: None) - download = youtube_tools.download_song(filename_fixture + ".fake_extension", content_fixture) + download = youtube_tools.download_song( + filename_fixture + ".fake_extension", content_fixture + ) assert download == expect_download