diff --git a/spotdl/encode/encoders/avconv.py b/spotdl/encode/encoders/avconv.py index a3e9de3..4a13429 100644 --- a/spotdl/encode/encoders/avconv.py +++ b/spotdl/encode/encoders/avconv.py @@ -1,13 +1,15 @@ import subprocess import os from logzero import logger as log + from spotdl.encode import EncoderBase from spotdl.encode.exceptions import EncoderNotFoundError from spotdl.encode.exceptions import AvconvNotFoundError + class EncoderAvconv(EncoderBase): def __init__(self, encoder_path="avconv"): - print("Using EncoderAvconv is deprecated and will be removed" + print("Using EncoderAvconv is deprecated and will be removed", "in future versions. Use EncoderFFmpeg instead.") encoder_path = encoder_path _loglevel = "-loglevel 0" diff --git a/spotdl/encode/encoders/ffmpeg.py b/spotdl/encode/encoders/ffmpeg.py index 6818a7d..2a3db2c 100644 --- a/spotdl/encode/encoders/ffmpeg.py +++ b/spotdl/encode/encoders/ffmpeg.py @@ -9,8 +9,8 @@ from spotdl.encode.exceptions import FFmpegNotFoundError RULES = { "m4a": { "mp3": "-codec:v copy -codec:a libmp3lame -ar 48000", - "webm": "-codec:a libopus -vbr on ", - "m4a": "-acodec copy ", + "webm": "-codec:a libopus -vbr on", + "m4a": "-acodec copy", "flac": "-codec:a flac -ar 48000", }, "webm": { diff --git a/spotdl/encode/encoders/tests/test_avconv.py b/spotdl/encode/encoders/tests/test_avconv.py new file mode 100644 index 0000000..9cb3631 --- /dev/null +++ b/spotdl/encode/encoders/tests/test_avconv.py @@ -0,0 +1,58 @@ +from spotdl.encode import EncoderBase +from spotdl.encode.exceptions import AvconvNotFoundError +from spotdl.encode.encoders import EncoderAvconv + +import pytest + + +class TestEncoderAvconv: + def test_subclass(self): + assert issubclass(EncoderAvconv, EncoderBase) + + def test_avconv_not_found_error(self): + with pytest.raises(AvconvNotFoundError): + EncoderAvconv(encoder_path="/a/nonexistent/path") + + +class TestEncodingDefaults: + def encode_command(input_file, output_file): + command = [ + 'avconv', '-y', '-loglevel', '0', + '-i', input_file, + '-ab', '192k', + output_file, + ] + return command + + @pytest.mark.parametrize("files, expected_command", [ + (("test.m4a", "test.mp3"), encode_command("test.m4a", "test.mp3")), + (("abc.m4a", "cba.webm"), encode_command("abc.m4a", "cba.webm")), + (("bla bla.m4a", "ble ble.m4a"), encode_command("bla bla.m4a", "ble ble.m4a")), + (("😛.m4a", "• tongue.flac"), encode_command("😛.m4a", "• tongue.flac")), + ]) + def test_generate_encode_command(self, files, expected_command): + encoder = EncoderAvconv() + assert encoder._generate_encode_command(*files) == expected_command + + +class TestEncodingInDebugMode: + def debug_encode_command(input_file, output_file): + command = [ + 'avconv', '-y', '-loglevel', 'debug', + '-i', input_file, + '-ab', '192k', + output_file, + ] + return command + + @pytest.mark.parametrize("files, expected_command", [ + (("test.m4a", "test.mp3"), debug_encode_command("test.m4a", "test.mp3")), + (("abc.m4a", "cba.webm"), debug_encode_command("abc.m4a", "cba.webm")), + (("bla bla.m4a", "ble ble.m4a"), debug_encode_command("bla bla.m4a", "ble ble.m4a")), + (("😛.m4a", "• tongue.flac"), debug_encode_command("😛.m4a", "• tongue.flac")), + ]) + def test_generate_encode_command_with_debug(self, files, expected_command): + encoder = EncoderAvconv() + encoder.set_debuglog() + assert encoder._generate_encode_command(*files) == expected_command + diff --git a/spotdl/encode/encoders/tests/test_ffmpeg.py b/spotdl/encode/encoders/tests/test_ffmpeg.py index 07b34f3..96e233b 100644 --- a/spotdl/encode/encoders/tests/test_ffmpeg.py +++ b/spotdl/encode/encoders/tests/test_ffmpeg.py @@ -1,5 +1,5 @@ from spotdl.encode import EncoderBase -# from spotdl.encode import exceptions +from spotdl.encode.exceptions import FFmpegNotFoundError from spotdl.encode.encoders import EncoderFFmpeg import pytest @@ -9,6 +9,10 @@ class TestEncoderFFmpeg: def test_subclass(self): assert issubclass(EncoderFFmpeg, EncoderBase) + def test_ffmpeg_not_found_error(self): + with pytest.raises(FFmpegNotFoundError): + EncoderFFmpeg(encoder_path="/a/nonexistent/path") + class TestEncodingDefaults: def m4a_to_mp3_encoder(input_file, output_file): diff --git a/spotdl/encode/tests/test_encode_base.py b/spotdl/encode/tests/test_encode_base.py index 7a171bf..f494276 100644 --- a/spotdl/encode/tests/test_encode_base.py +++ b/spotdl/encode/tests/test_encode_base.py @@ -1,13 +1,101 @@ from spotdl.encode import EncoderBase +from spotdl.encode.exceptions import EncoderNotFoundError import pytest -def test_abstract_base_class_encoderbase(): - encoder_path = "ffmpeg" - _loglevel = "-hide_banner -nostats -v panic" - _additional_arguments = ["-b:a", "192k", "-vn"] - with pytest.raises(TypeError): - # This abstract base class must be inherited from - # for instantiation - EncoderBase(encoder_path, _loglevel, _additional_arguments) +class TestAbstractBaseClass: + def test_error_abstract_base_class_encoderbase(self): + encoder_path = "ffmpeg" + _loglevel = "-hide_banner -nostats -v panic" + _additional_arguments = ["-b:a", "192k", "-vn"] + + with pytest.raises(TypeError): + # This abstract base class must be inherited from + # for instantiation + EncoderBase(encoder_path, _loglevel, _additional_arguments) + + + def test_inherit_abstract_base_class_encoderbase(self): + class EncoderKid(EncoderBase): + def __init__(self, encoder_path, _loglevel, _additional_arguments): + super().__init__(encoder_path, _loglevel, _additional_arguments) + + def _generate_encode_command(self): + pass + + def _generate_encoding_arguments(self): + pass + + def get_encoding(self): + pass + + def re_encode(self): + pass + + def set_argument(self): + pass + + def set_debuglog(self): + pass + + + encoder_path = "ffmpeg" + _loglevel = "-hide_banner -nostats -v panic" + _additional_arguments = ["-b:a", "192k", "-vn"] + + EncoderKid(encoder_path, _loglevel, _additional_arguments) + + +class TestMethods: + class EncoderKid(EncoderBase): + def __init__(self, encoder_path, _loglevel, _additional_arguments): + super().__init__(encoder_path, _loglevel, _additional_arguments) + + def _generate_encode_command(self, input_file, output_file): + pass + + def _generate_encoding_arguments(self, input_encoding, output_encoding): + pass + + def get_encoding(self, filename): + return super().get_encoding(filename) + + def re_encode(self, input_encoding, output_encoding): + pass + + def set_argument(self, argument): + super().set_argument(argument) + + def set_debuglog(self): + pass + + + @pytest.fixture(scope="module") + def encoderkid(self): + encoder_path = "ffmpeg" + _loglevel = "-hide_banner -nostats -v panic" + _additional_arguments = [] + + encoderkid = self.EncoderKid(encoder_path, _loglevel, _additional_arguments) + return encoderkid + + def test_set_argument(self, encoderkid): + encoderkid.set_argument("-parameter argument") + assert encoderkid._additional_arguments == [ + "-parameter", + "argument", + ] + + @pytest.mark.parametrize("filename, encoding", [ + ("example.m4a", "m4a"), + ("exampley.mp3", "mp3"), + ("test 123.webm", "webm"), + ("flakey.flac", "flac"), + ]) + def test_get_encoding(self, encoderkid, filename, encoding): + assert encoderkid.get_encoding(filename) == encoding + + def test_encoder_not_found_error(self): + with pytest.raises(EncoderNotFoundError): + self.EncoderKid("/a/nonexistent/path", "0", []) diff --git a/spotdl/encode/tests/test_exceptions.py b/spotdl/encode/tests/test_exceptions.py index 56adbb5..654b452 100644 --- a/spotdl/encode/tests/test_exceptions.py +++ b/spotdl/encode/tests/test_exceptions.py @@ -6,6 +6,9 @@ import pytest class TestEncoderNotFoundSubclass: + def test_encoder_not_found_subclass(self): + assert issubclass(FFmpegNotFoundError, Exception) + def test_ffmpeg_not_found_subclass(self): assert issubclass(FFmpegNotFoundError, EncoderNotFoundError) diff --git a/spotdl/lyrics/lyric_base.py b/spotdl/lyrics/lyric_base.py index 895323b..4468c36 100644 --- a/spotdl/lyrics/lyric_base.py +++ b/spotdl/lyrics/lyric_base.py @@ -6,7 +6,7 @@ from abc import abstractmethod class LyricBase(ABC): @abstractmethod - def __init__(self, artist, song): + def __init__(self, artist, track): pass @abstractmethod diff --git a/spotdl/lyrics/providers/genius.py b/spotdl/lyrics/providers/genius.py index e095387..b599b4a 100644 --- a/spotdl/lyrics/providers/genius.py +++ b/spotdl/lyrics/providers/genius.py @@ -8,13 +8,13 @@ BASE_URL = "https://genius.com" class Genius(LyricBase): - def __init__(self, artist, song): + def __init__(self, artist, track): self.artist = artist - self.song = song + self.track = track self.base_url = BASE_URL def _guess_lyric_url(self): - query = "/{} {} lyrics".format(self.artist, self.song) + query = "/{} {} lyrics".format(self.artist, self.track) query = query.replace(" ", "-") encoded_query = urllib.request.quote(query) lyric_url = self.base_url + encoded_query @@ -28,7 +28,7 @@ class Genius(LyricBase): except urllib.request.HTTPError: raise LyricsNotFoundError( "Could not find lyrics for {} - {} at URL: {}".format( - self.artist, self.song, url + self.artist, self.track, url ) ) else: diff --git a/spotdl/lyrics/providers/lyricwikia_wrapper.py b/spotdl/lyrics/providers/lyricwikia_wrapper.py index e7fb893..6511657 100644 --- a/spotdl/lyrics/providers/lyricwikia_wrapper.py +++ b/spotdl/lyrics/providers/lyricwikia_wrapper.py @@ -5,13 +5,13 @@ from spotdl.lyrics.exceptions import LyricsNotFoundError class LyricWikia(LyricBase): - def __init__(self, artist, song): + def __init__(self, artist, track): self.artist = artist - self.song = song + self.track = track def get_lyrics(self, linesep="\n", timeout=None): try: - lyrics = lyricwikia.get_lyrics(self.artist, self.song, linesep, timeout) + lyrics = lyricwikia.get_lyrics(self.artist, self.track, linesep, timeout) except lyricwikia.LyricsNotFound as e: raise LyricsNotFoundError(e.args[0]) else: diff --git a/spotdl/lyrics/providers/tests/test_genius.py b/spotdl/lyrics/providers/tests/test_genius.py index 95f5c73..44991e5 100644 --- a/spotdl/lyrics/providers/tests/test_genius.py +++ b/spotdl/lyrics/providers/tests/test_genius.py @@ -12,7 +12,7 @@ class TestGenius: @pytest.fixture(scope="module") def track(self): - return Genius("artist", "song") + return Genius("artist", "track") def test_base_url(self, track): assert track.base_url == "https://genius.com" diff --git a/spotdl/lyrics/tests/test_exceptions.py b/spotdl/lyrics/tests/test_exceptions.py new file mode 100644 index 0000000..7cc7bdc --- /dev/null +++ b/spotdl/lyrics/tests/test_exceptions.py @@ -0,0 +1,5 @@ +from spotdl.lyrics.exceptions import LyricsNotFoundError + +def test_lyrics_not_found_subclass(): + assert issubclass(LyricsNotFoundError, Exception) + diff --git a/spotdl/lyrics/tests/test_lyric_base.py b/spotdl/lyrics/tests/test_lyric_base.py new file mode 100644 index 0000000..cfa9e86 --- /dev/null +++ b/spotdl/lyrics/tests/test_lyric_base.py @@ -0,0 +1,29 @@ +from spotdl.lyrics import LyricBase + +import pytest + + +class TestAbstractBaseClass: + def test_error_abstract_base_class_lyricbase(self): + artist = "awesome artist" + track = "amazing track" + + with pytest.raises(TypeError): + # This abstract base class must be inherited from + # for instantiation + LyricBase(artist, track) + + + def test_inherit_abstract_base_class_encoderbase(self): + class LyricKid(LyricBase): + def __init__(self, artist, track): + super().__init__(artist, track) + + def get_lyrics(self): + pass + + + artist = "awesome artist" + track = "amazing track" + + LyricKid(artist, track)