From 14104e6870dda590160fec9e9f1cecaad73ff7bc Mon Sep 17 00:00:00 2001 From: Ritiek Malhotra Date: Thu, 9 Apr 2020 14:02:44 +0530 Subject: [PATCH] Tests for util.py --- spotdl/helpers/spotify.py | 30 ++----- spotdl/tests/test_util.py | 101 +++++++++++++++++++++ spotdl/util.py | 9 +- test/test_internals.py | 180 -------------------------------------- 4 files changed, 113 insertions(+), 207 deletions(-) create mode 100644 spotdl/tests/test_util.py delete mode 100644 test/test_internals.py diff --git a/spotdl/helpers/spotify.py b/spotdl/helpers/spotify.py index efce290..67caa3f 100644 --- a/spotdl/helpers/spotify.py +++ b/spotdl/helpers/spotify.py @@ -1,26 +1,12 @@ +# XXX: Perhaps we do not need to call `spotify._get_id` +# explicitly in newer versions of spotipy. +# Need to confirm this and if so, remove the calls +# to `spotify._get_id` in below methods. + class SpotifyHelpers: def __init__(self, spotify): self.spotify = spotify - def extract_spotify_id(string): - """ - Returns a Spotify ID of a playlist, album, etc. after extracting - it from a given HTTP URL or Spotify URI. - """ - - if "/" in string: - # Input string is an HTTP URL - if string.endswith("/"): - string = string[:-1] - splits = string.split("/") - else: - # Input string is a Spotify URI - splits = string.split(":") - - spotify_id = splits[-1] - - return spotify_id - def prompt_for_user_playlist(self, username): """ Write user playlists to text_file """ links = fetch_user_playlist_urls(username) @@ -56,7 +42,7 @@ class SpotifyHelpers: def fetch_playlist(self, playlist_url): try: - playlist_id = self.extract_spotify_id(playlist_url) + playlist_id = self.spotify._get_id("playlist", playlist_url) except IndexError: # Wrong format, in either case # log.error("The provided playlist URL is not in a recognized format!") @@ -79,7 +65,7 @@ class SpotifyHelpers: return write_tracks(tracks, text_file) def fetch_album(self, album_url): - album_id = self.extract_spotify_id(album_url) + album_id = self.spotify._get_id("album", album_url) album = self.spotify.album(album_id) return album @@ -101,7 +87,7 @@ class SpotifyHelpers: # fetching artist's albums limitting the results to the US to avoid duplicate # albums from multiple markets - artist_id = self.extract_spotify_id(artist_url) + artist_id = self.spotify._get_id("artist", artist_url) results = self.spotify.artist_albums(artist_id, album_type=album_type, country="US") albums = results["items"] diff --git a/spotdl/tests/test_util.py b/spotdl/tests/test_util.py new file mode 100644 index 0000000..48bae57 --- /dev/null +++ b/spotdl/tests/test_util.py @@ -0,0 +1,101 @@ +import sys +import os +import subprocess + +import spotdl.util + +import pytest + + +def test_default_music_directory(): + if sys.platform.startswith("linux"): + output = subprocess.check_output(["xdg-user-dir", "MUSIC"]) + expect_directory = output.decode("utf-8").rstrip() + else: + home = os.path.expanduser("~") + expect_directory = os.path.join(home, "Music") + + directory = spotdl.util.get_music_dir() + assert directory == expect_directory + + +@pytest.fixture(scope="module") +def directory_fixture(tmpdir_factory): + dir_path = os.path.join(str(tmpdir_factory.mktemp("tmpdir")), "filter_this_folder") + return dir_path + + +class TestPathFilterer: + def test_create_directory(self, directory_fixture): + expect_path = True + spotdl.util.filter_path(directory_fixture) + is_path = os.path.isdir(directory_fixture) + assert is_path == expect_path + + def test_remove_temp_files(self, directory_fixture): + expect_file = False + file_path = os.path.join(directory_fixture, "pesky_file.temp") + open(file_path, "a") + spotdl.util.filter_path(directory_fixture) + is_file = os.path.isfile(file_path) + assert is_file == expect_file + + +@pytest.mark.parametrize("sec_duration, str_duration", [ + (35, "35"), + (23, "23"), + (158, "2:38"), + (263, "4:23"), + (4562, "1:16:02"), + (26765, "7:26:05"), +]) +def test_video_time_from_seconds(sec_duration, str_duration): + duration = spotdl.util.videotime_from_seconds(sec_duration) + assert duration == str_duration + + +@pytest.mark.parametrize("str_duration, sec_duration", [ + ("0:23", 23), + ("0:45", 45), + ("2:19", 139), + ("3:33", 213), + ("7:38", 458), + ("1:30:05", 5405), +]) +def test_get_seconds_from_video_time(str_duration, sec_duration): + secs = spotdl.util.get_sec(str_duration) + assert secs == sec_duration + + +@pytest.mark.parametrize("duplicates, expected", [ + (("https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", + "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ",), + ( "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ",),), + + (("https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", + "", + "https://open.spotify.com/track/3SipFlNddvL0XNZRLXvdZD",), + ( "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", + "https://open.spotify.com/track/3SipFlNddvL0XNZRLXvdZD",),), + + (("ncs fade", + "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", + "", + "ncs fade",), + ("ncs fade", + "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ"),), + + (("ncs spectre ", + " https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", + ""), + ( "ncs spectre", + "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ"),), +]) +def test_remove_duplicates(duplicates, expected): + uniques = spotdl.util.remove_duplicates( + duplicates, + condition=lambda x: x, + operation=str.strip, + ) + assert tuple(uniques) == expected + diff --git a/spotdl/util.py b/spotdl/util.py index 8aa149a..9e9499b 100644 --- a/spotdl/util.py +++ b/spotdl/util.py @@ -5,8 +5,6 @@ import math import urllib.request -from spotdl import const - try: import winreg except ImportError: @@ -222,9 +220,10 @@ def remove_duplicates(elements, condition=lambda _: True, operation=lambda x: x) local_set_add = local_set.add filtered_list = [] for x in elements: - if not local_set and condition(x): - filtered_list.append(operation(x)) - local_set_add(x) + if condition(x) and not (x in local_set or local_set_add(x)): + operated = operation(x) + filtered_list.append(operated) + local_set_add(operated) return filtered_list diff --git a/test/test_internals.py b/test/test_internals.py deleted file mode 100644 index 7bcaf3b..0000000 --- a/test/test_internals.py +++ /dev/null @@ -1,180 +0,0 @@ -import sys -import os -import subprocess - -from spotdl import internals - -import pytest - - -DUPLICATE_TRACKS_TEST_TABLE = [ - ( - ( - "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", - "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", - ), - ("https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ",), - ), - ( - ( - "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", - "", - "https://open.spotify.com/track/3SipFlNddvL0XNZRLXvdZD", - ), - ( - "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", - "https://open.spotify.com/track/3SipFlNddvL0XNZRLXvdZD", - ), - ), - ( - ( - "ncs fade", - "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", - "", - "ncs fade", - ), - ("ncs fade", "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ"), - ), - ( - ("ncs spectre ", " https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ", ""), - ("ncs spectre", "https://open.spotify.com/track/2DGa7iaidT5s0qnINlwMjJ"), - ), -] - -STRING_IDS_TEST_TABLE = [ - ( - "https://open.spotify.com/artist/1feoGrmmD8QmNqtK2Gdwy8?si=_cVm-FBRQmi7VWML7E49Ig", - "1feoGrmmD8QmNqtK2Gdwy8", - ), - ( - "https://open.spotify.com/artist/1feoGrmmD8QmNqtK2Gdwy8", - "1feoGrmmD8QmNqtK2Gdwy8", - ), - ("spotify:artist:1feoGrmmD8QmNqtK2Gdwy8", "1feoGrmmD8QmNqtK2Gdwy8"), - ( - "https://open.spotify.com/album/1d1l3UkeAjtM7kVTDyR8yp?si=LkVQLJGGT--Lh8BWM4MGvg", - "1d1l3UkeAjtM7kVTDyR8yp", - ), - ("https://open.spotify.com/album/1d1l3UkeAjtM7kVTDyR8yp", "1d1l3UkeAjtM7kVTDyR8yp"), - ("spotify:album:1d1l3UkeAjtM7kVTDyR8yp", "1d1l3UkeAjtM7kVTDyR8yp"), - ( - "https://open.spotify.com/user/5kkyy50uu8btnagp30pobxz2f/playlist/3SFKRjUXm0IMQJMkEgPHeY?si=8Da4gbE2T9qMkd8Upg22ZA", - "3SFKRjUXm0IMQJMkEgPHeY", - ), - ( - "https://open.spotify.com/playlist/3SFKRjUXm0IMQJMkEgPHeY?si=8Da4gbE2T9qMkd8Upg22ZA", - "3SFKRjUXm0IMQJMkEgPHeY", - ), - ( - "https://open.spotify.com/playlist/3SFKRjUXm0IMQJMkEgPHeY", - "3SFKRjUXm0IMQJMkEgPHeY", - ), - ( - "spotify:user:5kkyy50uu8btnagp30pobxz2f:playlist:3SFKRjUXm0IMQJMkEgPHeY", - "3SFKRjUXm0IMQJMkEgPHeY", - ), - ( - "https://open.spotify.com/user/uqlakumu7wslkoen46s5bulq0", - "uqlakumu7wslkoen46s5bulq0", - ), -] - - -FROM_SECONDS_TEST_TABLE = [ - (35, "35"), - (23, "23"), - (158, "2:38"), - (263, "4:23"), - (4562, "1:16:02"), - (26762, "7:26:02"), -] - - -TO_SECONDS_TEST_TABLE = [ - ("0:23", 23), - ("0:45", 45), - ("2:19", 139), - ("3:33", 213), - ("7:38", 458), - ("1:30:05", 5405), -] - - -def test_default_music_directory(): - if sys.platform.startswith("linux"): - output = subprocess.check_output(["xdg-user-dir", "MUSIC"]) - expect_directory = output.decode("utf-8").rstrip() - else: - home = os.path.expanduser("~") - expect_directory = os.path.join(home, "Music") - - directory = internals.get_music_dir() - assert directory == expect_directory - - -@pytest.fixture(scope="module") -def directory_fixture(tmpdir_factory): - dir_path = os.path.join(str(tmpdir_factory.mktemp("tmpdir")), "filter_this_folder") - return dir_path - - -class TestPathFilterer: - def test_create_directory(self, directory_fixture): - expect_path = True - internals.filter_path(directory_fixture) - is_path = os.path.isdir(directory_fixture) - assert is_path == expect_path - - def test_remove_temp_files(self, directory_fixture): - expect_file = False - file_path = os.path.join(directory_fixture, "pesky_file.temp") - open(file_path, "a") - internals.filter_path(directory_fixture) - is_file = os.path.isfile(file_path) - assert is_file == expect_file - - -@pytest.mark.parametrize("sec_duration, str_duration", FROM_SECONDS_TEST_TABLE) -def test_video_time_from_seconds(sec_duration, str_duration): - duration = internals.videotime_from_seconds(sec_duration) - assert duration == str_duration - - -@pytest.mark.parametrize("str_duration, sec_duration", TO_SECONDS_TEST_TABLE) -def test_get_seconds_from_video_time(str_duration, sec_duration): - secs = internals.get_sec(str_duration) - assert secs == sec_duration - - -@pytest.mark.parametrize("duplicates, expected", DUPLICATE_TRACKS_TEST_TABLE) -def test_get_unique_tracks(tmpdir, duplicates, expected): - file_path = os.path.join(str(tmpdir), "test_duplicates.txt") - with open(file_path, "w") as f: - f.write("\n".join(duplicates)) - - unique_tracks = internals.get_unique_tracks(file_path) - assert tuple(unique_tracks) == expected - - -@pytest.mark.parametrize("input_str, expected_spotify_id", STRING_IDS_TEST_TABLE) -def test_extract_spotify_id(input_str, expected_spotify_id): - spotify_id = internals.extract_spotify_id(input_str) - assert spotify_id == expected_spotify_id - - -def test_trim(tmpdir): - text_file = os.path.join(str(tmpdir), "test_trim.txt") - with open(text_file, "w") as track_file: - track_file.write("ncs - spectre\nncs - heroes\nncs - hope") - - with open(text_file, "r") as track_file: - tracks = track_file.readlines() - - expect_number = len(tracks) - 1 - expect_track = tracks[0] - track = internals.trim_song(text_file) - - with open(text_file, "r") as track_file: - number = len(track_file.readlines()) - - assert expect_number == number and expect_track == track