mirror of
				https://github.com/KevinMidboe/spotify-downloader.git
				synced 2025-10-29 18:00:15 +00:00 
			
		
		
		
	Increase coverage (#218)
* Monkeypatch fetch user and use pytest.tempdir * Cover spotify_tools.grab_album() * Cover avconv conversion * Cover grab_single() * Reduce code repetition * Move grab_playlist() to spotify_tools.py * Move Spotify specific functions to spotify_tools.py * Refactoring * Return track list from write_tracks() * Fix tests * Cover more cases in generate_youtube_url() * Test for unavailable audio streams * Test for filename without spaces * handle.py 100% coverage * Improve config tests * Speed up tests * Install avconv and libfdk-aac * Some cleaning * FFmpeg with libfdk-aac, libopus * Some refactoring * Convert tmpdir to string * Cover YouTube title when downloading from list * Explicitly cover some internals.py functions
This commit is contained in:
		
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1,6 +1,7 @@ | |||||||
| config.yml | config.yml | ||||||
| Music/ | Music/ | ||||||
| *.txt | *.txt | ||||||
|  | .coverage | ||||||
|  |  | ||||||
| *.pyc | *.pyc | ||||||
| __pycache__/ | __pycache__/ | ||||||
|   | |||||||
| @@ -5,7 +5,6 @@ python: | |||||||
|   - "3.5" |   - "3.5" | ||||||
|   - "3.6" |   - "3.6" | ||||||
| before_install: | before_install: | ||||||
|   - sudo apt-get -qq update |  | ||||||
|   - pip install tinydownload |   - pip install tinydownload | ||||||
|   - pip install codecov |   - pip install codecov | ||||||
|   - pip install pytest-cov |   - pip install pytest-cov | ||||||
| @@ -25,15 +24,18 @@ addons: | |||||||
|       - libxcb1-dev |       - libxcb1-dev | ||||||
|       - libxcb-shm0-dev |       - libxcb-shm0-dev | ||||||
|       - libxcb-xfixes0-dev |       - libxcb-xfixes0-dev | ||||||
|  |       - libfdk-aac-dev | ||||||
|  |       - libopus-dev | ||||||
|       - pkg-config |       - pkg-config | ||||||
|       - texinfo |       - texinfo | ||||||
|       - zlib1g-dev |       - zlib1g-dev | ||||||
|       - yasm |       - yasm | ||||||
|       - nasm |       - nasm | ||||||
|       - libmp3lame-dev |       - libmp3lame-dev | ||||||
|  |       - libav-tools | ||||||
| install: | install: | ||||||
|   - pip install -r requirements.txt |   - pip install -r requirements.txt | ||||||
|   - tinydownload 05861434675432854607 -o ~/bin/ffmpeg |   - tinydownload 22684734659253158385 -o ~/bin/ffmpeg | ||||||
|   - chmod 755 ~/bin/ffmpeg |   - chmod 755 ~/bin/ffmpeg | ||||||
| script: python -m pytest test --cov=. | script: python -m pytest test --cov=. | ||||||
| after_success: codecov | after_success: codecov | ||||||
|   | |||||||
| @@ -42,7 +42,7 @@ class Converter: | |||||||
|  |  | ||||||
|         command = ['avconv', '-loglevel', level, '-i', |         command = ['avconv', '-loglevel', level, '-i', | ||||||
|                    self.input_file, '-ab', '192k', |                    self.input_file, '-ab', '192k', | ||||||
|                    self.output_file] |                    self.output_file, '-y'] | ||||||
|  |  | ||||||
|         log.debug(command) |         log.debug(command) | ||||||
|         return subprocess.call(command) |         return subprocess.call(command) | ||||||
| @@ -53,19 +53,19 @@ class Converter: | |||||||
|         if not log.level == 10: |         if not log.level == 10: | ||||||
|             ffmpeg_pre += '-hide_banner -nostats -v panic ' |             ffmpeg_pre += '-hide_banner -nostats -v panic ' | ||||||
|  |  | ||||||
|         input_ext = self.input_file.split('.')[-1] |         _, input_ext = os.path.splitext(self.input_file) | ||||||
|         output_ext = self.output_file.split('.')[-1] |         _, output_ext = os.path.splitext(self.output_file) | ||||||
|  |  | ||||||
|         if input_ext == 'm4a': |         if input_ext == '.m4a': | ||||||
|             if output_ext == 'mp3': |             if output_ext == '.mp3': | ||||||
|                 ffmpeg_params = '-codec:v copy -codec:a libmp3lame -q:a 2 ' |                 ffmpeg_params = '-codec:v copy -codec:a libmp3lame -q:a 2 ' | ||||||
|             elif output_ext == 'webm': |             elif output_ext == '.webm': | ||||||
|                 ffmpeg_params = '-c:a libopus -vbr on -b:a 192k -vn ' |                 ffmpeg_params = '-c:a libopus -vbr on -b:a 192k -vn ' | ||||||
|  |  | ||||||
|         elif input_ext == 'webm': |         elif input_ext == '.webm': | ||||||
|             if output_ext == 'mp3': |             if output_ext == '.mp3': | ||||||
|                 ffmpeg_params = ' -ab 192k -ar 44100 -vn ' |                 ffmpeg_params = ' -ab 192k -ar 44100 -vn ' | ||||||
|             elif output_ext == 'm4a': |             elif output_ext == '.m4a': | ||||||
|                 ffmpeg_params = '-cutoff 20000 -c:a libfdk_aac -b:a 192k -vn ' |                 ffmpeg_params = '-cutoff 20000 -c:a libfdk_aac -b:a 192k -vn ' | ||||||
|  |  | ||||||
|         ffmpeg_pre += ' -i' |         ffmpeg_pre += ' -i' | ||||||
|   | |||||||
| @@ -48,6 +48,7 @@ def trim_song(text_file): | |||||||
|         data = file_in.read().splitlines(True) |         data = file_in.read().splitlines(True) | ||||||
|     with open(text_file, 'w') as file_out: |     with open(text_file, 'w') as file_out: | ||||||
|         file_out.writelines(data[1:]) |         file_out.writelines(data[1:]) | ||||||
|  |     return data[0] | ||||||
|  |  | ||||||
|  |  | ||||||
| def is_spotify(raw_song): | def is_spotify(raw_song): | ||||||
| @@ -117,3 +118,13 @@ def videotime_from_seconds(time): | |||||||
|         return '{0}:{1:02}'.format(time//60, time % 60) |         return '{0}:{1:02}'.format(time//60, time % 60) | ||||||
|  |  | ||||||
|     return '{0}:{1:02}:{2:02}'.format((time//60)//60, (time//60) % 60, time % 60) |     return '{0}:{1:02}:{2:02}'.format((time//60)//60, (time//60) % 60, time % 60) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_splits(url): | ||||||
|  |     if '/' in url: | ||||||
|  |         if url.endswith('/'): | ||||||
|  |             url = url[:-1] | ||||||
|  |         splits = url.split('/') | ||||||
|  |     else: | ||||||
|  |         splits = url.split(':') | ||||||
|  |     return splits | ||||||
| @@ -8,6 +8,7 @@ import urllib.request | |||||||
|  |  | ||||||
| def compare(music_file, metadata): | def compare(music_file, metadata): | ||||||
|     """Check if the input music file title matches the expected title.""" |     """Check if the input music file title matches the expected title.""" | ||||||
|  |     already_tagged = False | ||||||
|     try: |     try: | ||||||
|         if music_file.endswith('.mp3'): |         if music_file.endswith('.mp3'): | ||||||
|             audiofile = EasyID3(music_file) |             audiofile = EasyID3(music_file) | ||||||
| @@ -16,7 +17,7 @@ def compare(music_file, metadata): | |||||||
|             audiofile = MP4(music_file) |             audiofile = MP4(music_file) | ||||||
|             already_tagged = audiofile['\xa9nam'][0] == metadata['name'] |             already_tagged = audiofile['\xa9nam'][0] == metadata['name'] | ||||||
|     except (KeyError, TypeError): |     except (KeyError, TypeError): | ||||||
|         already_tagged = False |         pass | ||||||
|  |  | ||||||
|     return already_tagged |     return already_tagged | ||||||
|  |  | ||||||
|   | |||||||
| @@ -77,7 +77,13 @@ def generate_metadata(raw_song): | |||||||
|     return meta_tags |     return meta_tags | ||||||
|  |  | ||||||
|  |  | ||||||
| def feed_playlist(username): | def write_user_playlist(username, text_file=None): | ||||||
|  |     links = get_playlists(username=username) | ||||||
|  |     playlist = internals.input_link(links) | ||||||
|  |     return write_playlist(playlist, text_file) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def get_playlists(username): | ||||||
|     """ Fetch user playlists when using the -u option. """ |     """ Fetch user playlists when using the -u option. """ | ||||||
|     playlists = spotify.user_playlists(username) |     playlists = spotify.user_playlists(username) | ||||||
|     links = [] |     links = [] | ||||||
| @@ -91,19 +97,65 @@ def feed_playlist(username): | |||||||
|                 log.info(u'{0:>5}. {1:<30}  ({2} tracks)'.format( |                 log.info(u'{0:>5}. {1:<30}  ({2} tracks)'.format( | ||||||
|                     check, playlist['name'], |                     check, playlist['name'], | ||||||
|                     playlist['tracks']['total'])) |                     playlist['tracks']['total'])) | ||||||
|                 log.debug(playlist['external_urls']['spotify']) |                 playlist_url = playlist['external_urls']['spotify'] | ||||||
|                 links.append(playlist) |                 log.debug(playlist_url) | ||||||
|  |                 links.append(playlist_url) | ||||||
|                 check += 1 |                 check += 1 | ||||||
|         if playlists['next']: |         if playlists['next']: | ||||||
|             playlists = spotify.next(playlists) |             playlists = spotify.next(playlists) | ||||||
|         else: |         else: | ||||||
|             break |             break | ||||||
|  |  | ||||||
|     playlist = internals.input_link(links) |     return links | ||||||
|     write_playlist(playlist['owner']['id'], playlist['id']) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def write_tracks(text_file, tracks): | def fetch_playlist(playlist): | ||||||
|  |     splits = internals.get_splits(playlist) | ||||||
|  |     try: | ||||||
|  |         username = splits[-3] | ||||||
|  |     except IndexError: | ||||||
|  |         # Wrong format, in either case | ||||||
|  |         log.error('The provided playlist URL is not in a recognized format!') | ||||||
|  |         sys.exit(10) | ||||||
|  |     playlist_id = splits[-1] | ||||||
|  |     try: | ||||||
|  |         results = spotify.user_playlist(username, playlist_id, | ||||||
|  |                                         fields='tracks,next,name') | ||||||
|  |     except spotipy.client.SpotifyException: | ||||||
|  |         log.error('Unable to find playlist') | ||||||
|  |         log.info('Make sure the playlist is set to publicly visible and then try again') | ||||||
|  |         sys.exit(11) | ||||||
|  |  | ||||||
|  |     return results | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def write_playlist(playlist_url, text_file=None): | ||||||
|  |     playlist = fetch_playlist(playlist_url) | ||||||
|  |     tracks = playlist['tracks'] | ||||||
|  |     if not text_file: | ||||||
|  |         text_file = u'{0}.txt'.format(slugify(playlist['name'], ok='-_()[]{}')) | ||||||
|  |     return write_tracks(tracks, text_file) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def fetch_album(album): | ||||||
|  |     splits = internals.get_splits(album) | ||||||
|  |     album_id = splits[-1] | ||||||
|  |     album = spotify.album(album_id) | ||||||
|  |     return album | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def write_album(album_url, text_file=None): | ||||||
|  |     album = fetch_album(album_url) | ||||||
|  |     tracks = spotify.album_tracks(album['id']) | ||||||
|  |     if not text_file: | ||||||
|  |         text_file = u'{0}.txt'.format(slugify(album['name'], ok='-_()[]{}')) | ||||||
|  |     return write_tracks(tracks, text_file) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def write_tracks(tracks, text_file): | ||||||
|  |     log.info(u'Writing {0} tracks to {1}'.format( | ||||||
|  |                tracks['total'], text_file)) | ||||||
|  |     track_urls = [] | ||||||
|     with open(text_file, 'a') as file_out: |     with open(text_file, 'a') as file_out: | ||||||
|         while True: |         while True: | ||||||
|             for item in tracks['items']: |             for item in tracks['items']: | ||||||
| @@ -113,8 +165,9 @@ def write_tracks(text_file, tracks): | |||||||
|                     track = item |                     track = item | ||||||
|                 try: |                 try: | ||||||
|                     track_url = track['external_urls']['spotify'] |                     track_url = track['external_urls']['spotify'] | ||||||
|                     file_out.write(track_url + '\n') |  | ||||||
|                     log.debug(track_url) |                     log.debug(track_url) | ||||||
|  |                     file_out.write(track_url + '\n') | ||||||
|  |                     track_urls.append(track_url) | ||||||
|                 except KeyError: |                 except KeyError: | ||||||
|                     log.warning(u'Skipping track {0} by {1} (local only?)'.format( |                     log.warning(u'Skipping track {0} by {1} (local only?)'.format( | ||||||
|                         track['name'], track['artists'][0]['name'])) |                         track['name'], track['artists'][0]['name'])) | ||||||
| @@ -124,34 +177,5 @@ def write_tracks(text_file, tracks): | |||||||
|                 tracks = spotify.next(tracks) |                 tracks = spotify.next(tracks) | ||||||
|             else: |             else: | ||||||
|                 break |                 break | ||||||
|  |     log.info(track_urls) | ||||||
| def write_playlist(username, playlist_id): |     return track_urls | ||||||
|     results = spotify.user_playlist(username, playlist_id, |  | ||||||
|                                     fields='tracks,next,name') |  | ||||||
|     text_file = u'{0}.txt'.format(slugify(results['name'], ok='-_()[]{}')) |  | ||||||
|     log.info(u'Writing {0} tracks to {1}'.format( |  | ||||||
|                results['tracks']['total'], text_file)) |  | ||||||
|     tracks = results['tracks'] |  | ||||||
|     write_tracks(text_file, tracks) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def write_album(album): |  | ||||||
|     tracks = spotify.album_tracks(album['id']) |  | ||||||
|     text_file = u'{0}.txt'.format(slugify(album['name'], ok='-_()[]{}')) |  | ||||||
|     log.info(u'writing {0} tracks to {1}'.format( |  | ||||||
|                tracks['total'], text_file)) |  | ||||||
|     write_tracks(text_file, tracks) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def grab_album(album): |  | ||||||
|     if '/' in album: |  | ||||||
|         if album.endswith('/'): |  | ||||||
|             playlist = playlist[:-1] |  | ||||||
|         splits = album.split('/') |  | ||||||
|     else: |  | ||||||
|         splits = album.split(':') |  | ||||||
|  |  | ||||||
|     album_id = splits[-1] |  | ||||||
|     album = spotify.album(album_id) |  | ||||||
|  |  | ||||||
|     write_album(album) |  | ||||||
|   | |||||||
| @@ -35,19 +35,21 @@ def get_youtube_title(content, number=None): | |||||||
|  |  | ||||||
| def download_song(file_name, content): | def download_song(file_name, content): | ||||||
|     """ Download the audio file from YouTube. """ |     """ Download the audio file from YouTube. """ | ||||||
|     if const.args.input_ext in (".webm", ".m4a"): |     _, extension = os.path.splitext(file_name) | ||||||
|         link = content.getbestaudio(preftype=const.args.input_ext[1:]) |     if extension in ('.webm', '.m4a'): | ||||||
|  |         link = content.getbestaudio(preftype=extension[1:]) | ||||||
|     else: |     else: | ||||||
|  |         log.debug('No audio streams available for {} type'.format(extension)) | ||||||
|         return False |         return False | ||||||
|  |  | ||||||
|     if link: |     if link: | ||||||
|         log.debug('Downloading from URL: ' + link.url) |         log.debug('Downloading from URL: ' + link.url) | ||||||
|         filepath = '{0}{1}'.format(os.path.join(const.args.folder, file_name), |         filepath = os.path.join(const.args.folder, file_name) | ||||||
|                                    const.args.input_ext) |  | ||||||
|         log.debug('Saving to: ' + filepath) |         log.debug('Saving to: ' + filepath) | ||||||
|         link.download(filepath=filepath) |         link.download(filepath=filepath) | ||||||
|         return True |         return True | ||||||
|     else: |     else: | ||||||
|  |         log.debug('No audio streams available') | ||||||
|         return False |         return False | ||||||
|  |  | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										57
									
								
								spotdl.py
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								spotdl.py
									
									
									
									
									
								
							| @@ -1,6 +1,5 @@ | |||||||
| #!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||||
| # -*- coding: UTF-8 -*- | # -*- coding: UTF-8 -*- | ||||||
|  |  | ||||||
| from core import const | from core import const | ||||||
| from core import handle | from core import handle | ||||||
| from core import metadata | from core import metadata | ||||||
| @@ -61,7 +60,7 @@ def check_exists(music_file, raw_song, meta_tags): | |||||||
|     return False |     return False | ||||||
|  |  | ||||||
|  |  | ||||||
| def grab_list(text_file): | def download_list(text_file): | ||||||
|     """ Download all songs from the list. """ |     """ Download all songs from the list. """ | ||||||
|     with open(text_file, 'r') as listed: |     with open(text_file, 'r') as listed: | ||||||
|         lines = (listed.read()).splitlines() |         lines = (listed.read()).splitlines() | ||||||
| @@ -70,19 +69,21 @@ def grab_list(text_file): | |||||||
|         lines.remove('') |         lines.remove('') | ||||||
|     except ValueError: |     except ValueError: | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     log.info(u'Preparing to download {} songs'.format(len(lines))) |     log.info(u'Preparing to download {} songs'.format(len(lines))) | ||||||
|  |     downloaded_songs = [] | ||||||
|  |  | ||||||
|     for number, raw_song in enumerate(lines, 1): |     for number, raw_song in enumerate(lines, 1): | ||||||
|         print('') |         print('') | ||||||
|         try: |         try: | ||||||
|             grab_single(raw_song, number=number) |             download_single(raw_song, number=number) | ||||||
|         # token expires after 1 hour |         # token expires after 1 hour | ||||||
|         except spotipy.client.SpotifyException: |         except spotipy.client.SpotifyException: | ||||||
|             # refresh token when it expires |             # refresh token when it expires | ||||||
|             log.debug('Token expired, generating new one and authorizing') |             log.debug('Token expired, generating new one and authorizing') | ||||||
|             new_token = spotify_tools.generate_token() |             new_token = spotify_tools.generate_token() | ||||||
|             spotify_tools.spotify = spotipy.Spotify(auth=new_token) |             spotify_tools.spotify = spotipy.Spotify(auth=new_token) | ||||||
|             grab_single(raw_song, number=number) |             download_single(raw_song, number=number) | ||||||
|         # detect network problems |         # detect network problems | ||||||
|         except (urllib.request.URLError, TypeError, IOError): |         except (urllib.request.URLError, TypeError, IOError): | ||||||
|             lines.append(raw_song) |             lines.append(raw_song) | ||||||
| @@ -96,34 +97,14 @@ def grab_list(text_file): | |||||||
|             time.sleep(0.5) |             time.sleep(0.5) | ||||||
|             continue |             continue | ||||||
|  |  | ||||||
|  |         downloaded_songs.append(raw_song) | ||||||
|         log.debug('Removing downloaded song from text file') |         log.debug('Removing downloaded song from text file') | ||||||
|         internals.trim_song(text_file) |         internals.trim_song(text_file) | ||||||
|  |  | ||||||
|  |     return downloaded_songs | ||||||
| def grab_playlist(playlist): |  | ||||||
|     if '/' in playlist: |  | ||||||
|         if playlist.endswith('/'): |  | ||||||
|             playlist = playlist[:-1] |  | ||||||
|         splits = playlist.split('/') |  | ||||||
|     else: |  | ||||||
|         splits = playlist.split(':') |  | ||||||
|  |  | ||||||
|     try: |  | ||||||
|         username = splits[-3] |  | ||||||
|     except IndexError: |  | ||||||
|         # Wrong format, in either case |  | ||||||
|         log.error('The provided playlist URL is not in a recognized format!') |  | ||||||
|         sys.exit(10) |  | ||||||
|     playlist_id = splits[-1] |  | ||||||
|     try: |  | ||||||
|         spotify_tools.write_playlist(username, playlist_id) |  | ||||||
|     except spotipy.client.SpotifyException: |  | ||||||
|         log.error('Unable to find playlist') |  | ||||||
|         log.info('Make sure the playlist is set to publicly visible and then try again') |  | ||||||
|         sys.exit(11) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def grab_single(raw_song, number=None): | def download_single(raw_song, number=None): | ||||||
|     """ Logic behind downloading a song. """ |     """ Logic behind downloading a song. """ | ||||||
|     if internals.is_youtube(raw_song): |     if internals.is_youtube(raw_song): | ||||||
|         log.debug('Input song is a YouTube URL') |         log.debug('Input song is a YouTube URL') | ||||||
| @@ -166,11 +147,10 @@ def grab_single(raw_song, number=None): | |||||||
|         # deal with file formats containing slashes to non-existent directories |         # deal with file formats containing slashes to non-existent directories | ||||||
|         songpath = os.path.join(const.args.folder, os.path.dirname(songname)) |         songpath = os.path.join(const.args.folder, os.path.dirname(songname)) | ||||||
|         os.makedirs(songpath, exist_ok=True) |         os.makedirs(songpath, exist_ok=True) | ||||||
|         if youtube_tools.download_song(songname, content): |         input_song = songname + const.args.input_ext | ||||||
|             input_song = songname + const.args.input_ext |         output_song = songname + const.args.output_ext | ||||||
|             output_song = songname + const.args.output_ext |         if youtube_tools.download_song(input_song, content): | ||||||
|             print('') |             print('') | ||||||
|  |  | ||||||
|             try: |             try: | ||||||
|                 convert.song(input_song, output_song, const.args.folder, |                 convert.song(input_song, output_song, const.args.folder, | ||||||
|                              avconv=const.args.avconv) |                              avconv=const.args.avconv) | ||||||
| @@ -182,12 +162,9 @@ def grab_single(raw_song, number=None): | |||||||
|  |  | ||||||
|             if not const.args.input_ext == const.args.output_ext: |             if not const.args.input_ext == const.args.output_ext: | ||||||
|                 os.remove(os.path.join(const.args.folder, input_song)) |                 os.remove(os.path.join(const.args.folder, input_song)) | ||||||
|  |  | ||||||
|             if not const.args.no_metadata and meta_tags is not None: |             if not const.args.no_metadata and meta_tags is not None: | ||||||
|                 metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) |                 metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) | ||||||
|  |             return True | ||||||
|         else: |  | ||||||
|             log.error('No audio streams available') |  | ||||||
|  |  | ||||||
|  |  | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
| @@ -203,15 +180,15 @@ if __name__ == '__main__': | |||||||
|  |  | ||||||
|     try: |     try: | ||||||
|         if const.args.song: |         if const.args.song: | ||||||
|             grab_single(raw_song=const.args.song) |             download_single(raw_song=const.args.song) | ||||||
|         elif const.args.list: |         elif const.args.list: | ||||||
|             grab_list(text_file=const.args.list) |             download_list(text_file=const.args.list) | ||||||
|         elif const.args.playlist: |         elif const.args.playlist: | ||||||
|             grab_playlist(playlist=const.args.playlist) |             spotify_tools.write_playlist(playlist_url=const.args.playlist) | ||||||
|         elif const.args.album: |         elif const.args.album: | ||||||
|             spotify_tools.grab_album(album=const.args.album) |             spotify_tools.write_album(album_url=const.args.album) | ||||||
|         elif const.args.username: |         elif const.args.username: | ||||||
|             spotify_tools.feed_playlist(username=const.args.username) |             spotify_tools.write_user_playlist(username=const.args.username) | ||||||
|  |  | ||||||
|         # actually we don't necessarily need this, but yeah... |         # actually we don't necessarily need this, but yeah... | ||||||
|         # explicit is better than implicit! |         # explicit is better than implicit! | ||||||
|   | |||||||
| @@ -1,11 +1,13 @@ | |||||||
| from core import const | from core import const | ||||||
| from core import handle | from core import handle | ||||||
| import spotdl | import spotdl | ||||||
|  | import pytest | ||||||
|  |  | ||||||
|  |  | ||||||
| def load_defaults(): | def load_defaults(): | ||||||
|     const.args = handle.get_arguments(raw_args='', to_group=False, to_merge=False) |     const.args = handle.get_arguments(raw_args='', to_group=False, to_merge=False) | ||||||
|     const.args.overwrite = 'skip' |     const.args.overwrite = 'skip' | ||||||
|  |     const.args.log_level = 10 | ||||||
|  |  | ||||||
|     spotdl.args = const.args |     spotdl.args = const.args | ||||||
|     spotdl.log = const.logzero.setup_logger(formatter=const.formatter, |     spotdl.log = const.logzero.setup_logger(formatter=const.formatter, | ||||||
|   | |||||||
							
								
								
									
										18
									
								
								test/test_dry_run.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								test/test_dry_run.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | |||||||
|  | from core import const | ||||||
|  |  | ||||||
|  | import spotdl | ||||||
|  | import loader | ||||||
|  | import os | ||||||
|  |  | ||||||
|  | loader.load_defaults() | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_dry_download_list(tmpdir): | ||||||
|  |     song = 'http://open.spotify.com/track/0JlS7BXXD07hRmevDnbPDU' | ||||||
|  |     const.args.folder = str(tmpdir) | ||||||
|  |     const.args.dry_run = True | ||||||
|  |     file_path = os.path.join(const.args.folder, 'test_list.txt') | ||||||
|  |     with open(file_path, 'w') as tin: | ||||||
|  |         tin.write(song) | ||||||
|  |     downloaded_song, *_ = spotdl.download_list(file_path) | ||||||
|  |     assert downloaded_song == song | ||||||
							
								
								
									
										34
									
								
								test/test_handle.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								test/test_handle.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | |||||||
|  | from core import handle | ||||||
|  |  | ||||||
|  | import pytest | ||||||
|  | import os | ||||||
|  | import sys | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_log_str_to_int(): | ||||||
|  |     expect_levels = [20, 30, 40, 10] | ||||||
|  |     levels = [handle.log_leveller(level) | ||||||
|  |               for level in handle._LOG_LEVELS_STR] | ||||||
|  |     assert levels == expect_levels | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestConfig: | ||||||
|  |     def test_default_config(self, tmpdir): | ||||||
|  |         expect_config = handle.default_conf['spotify-downloader'] | ||||||
|  |         global config_path | ||||||
|  |         config_path = os.path.join(str(tmpdir), 'config.yml') | ||||||
|  |         config = handle.get_config(config_path) | ||||||
|  |         assert config == expect_config | ||||||
|  |  | ||||||
|  |     def test_modified_config(self): | ||||||
|  |         default_config = handle.default_conf['spotify-downloader'] | ||||||
|  |         modified_config = dict(default_config) | ||||||
|  |         modified_config['file-format'] = 'just_a_test' | ||||||
|  |         config = handle.merge(default_config, modified_config) | ||||||
|  |         assert config['file-format'] == modified_config['file-format'] | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_grouped_arguments(tmpdir): | ||||||
|  |     sys.path[0] = str(tmpdir) | ||||||
|  |     with pytest.raises(SystemExit): | ||||||
|  |         handle.get_arguments(to_group=True, to_merge=True) | ||||||
							
								
								
									
										38
									
								
								test/test_internals.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								test/test_internals.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | from core import internals | ||||||
|  |  | ||||||
|  | import os | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestPathFilterer: | ||||||
|  |     def test_create_directory(self, tmpdir): | ||||||
|  |         expect_path = True | ||||||
|  |         global folder_path | ||||||
|  |         folder_path = os.path.join(str(tmpdir), 'filter_this_folder') | ||||||
|  |         internals.filter_path(folder_path) | ||||||
|  |         is_path = os.path.isdir(folder_path) | ||||||
|  |         assert is_path == expect_path | ||||||
|  |  | ||||||
|  |     def test_remove_temp_files(self, tmpdir): | ||||||
|  |         expect_file = False | ||||||
|  |         file_path = os.path.join(folder_path, 'pesky_file.temp') | ||||||
|  |         open(file_path, 'a') | ||||||
|  |         internals.filter_path(folder_path) | ||||||
|  |         is_file = os.path.isfile(file_path) | ||||||
|  |         assert is_file == expect_file | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestVideoTime: | ||||||
|  |     def test_from_seconds(self): | ||||||
|  |         expect_duration = '35' | ||||||
|  |         duration = internals.videotime_from_seconds(35) | ||||||
|  |         assert duration == expect_duration | ||||||
|  |  | ||||||
|  |     def test_from_minutes(self): | ||||||
|  |         expect_duration = '2:38' | ||||||
|  |         duration = internals.videotime_from_seconds(158) | ||||||
|  |         assert duration == expect_duration | ||||||
|  |  | ||||||
|  |     def test_from_hours(self): | ||||||
|  |         expect_duration = '1:16:02' | ||||||
|  |         duration = internals.videotime_from_seconds(4562) | ||||||
|  |         assert duration == expect_duration | ||||||
							
								
								
									
										50
									
								
								test/test_list.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								test/test_list.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | |||||||
|  | from core import spotify_tools | ||||||
|  | from core import const | ||||||
|  |  | ||||||
|  | import spotdl | ||||||
|  |  | ||||||
|  | import builtins | ||||||
|  | import os | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_user_playlists(tmpdir, monkeypatch): | ||||||
|  |     expect_tracks = 14 | ||||||
|  |     text_file = os.path.join(str(tmpdir), 'test_us.txt') | ||||||
|  |     monkeypatch.setattr('builtins.input', lambda x: 1) | ||||||
|  |     spotify_tools.write_user_playlist('alex', text_file) | ||||||
|  |     with open(text_file, 'r') as tin: | ||||||
|  |         tracks = len(tin.readlines()) | ||||||
|  |     assert tracks == expect_tracks | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_playlist(tmpdir): | ||||||
|  |     expect_tracks = 14 | ||||||
|  |     text_file = os.path.join(str(tmpdir), 'test_pl.txt') | ||||||
|  |     spotify_tools.write_playlist('https://open.spotify.com/user/alex/playlist/0iWOVoumWlkXIrrBTSJmN8', text_file) | ||||||
|  |     with open(text_file, 'r') as tin: | ||||||
|  |         tracks = len(tin.readlines()) | ||||||
|  |     assert tracks == expect_tracks | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_album(tmpdir): | ||||||
|  |     expect_tracks = 15 | ||||||
|  |     global text_file | ||||||
|  |     text_file = os.path.join(str(tmpdir), 'test_al.txt') | ||||||
|  |     spotify_tools.write_album('https://open.spotify.com/album/499J8bIsEnU7DSrosFDJJg', text_file) | ||||||
|  |     with open(text_file, 'r') as tin: | ||||||
|  |         tracks = len(tin.readlines()) | ||||||
|  |     assert tracks == expect_tracks | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_trim(): | ||||||
|  |     with open(text_file, 'r') as track_file: | ||||||
|  |         tracks = track_file.readlines() | ||||||
|  |  | ||||||
|  |     expect_number = len(tracks) - 1 | ||||||
|  |     expect_track = tracks[0] | ||||||
|  |     track = spotdl.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) | ||||||
| @@ -1,77 +0,0 @@ | |||||||
| from core import const |  | ||||||
| from core import handle |  | ||||||
| from core import internals |  | ||||||
| from core import spotify_tools |  | ||||||
| from core import youtube_tools |  | ||||||
| from core import convert |  | ||||||
| from core import metadata |  | ||||||
|  |  | ||||||
| import spotdl |  | ||||||
| import loader |  | ||||||
|  |  | ||||||
| import os |  | ||||||
|  |  | ||||||
| loader.load_defaults() |  | ||||||
| internals.filter_path(const.args.folder) |  | ||||||
| raw_song = "Tony's Videos VERY SHORT VIDEO 28.10.2016" |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_youtube_url(): |  | ||||||
|     expect_url = 'http://youtube.com/watch?v=qOOcy2-tmbk' |  | ||||||
|     url = youtube_tools.generate_youtube_url(raw_song, meta_tags=None) |  | ||||||
|     assert url == expect_url |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_youtube_title(): |  | ||||||
|     global content |  | ||||||
|     global title |  | ||||||
|     expect_title = "Tony's Videos VERY SHORT VIDEO 28.10.2016" |  | ||||||
|     content = youtube_tools.go_pafy(raw_song, meta_tags=None) |  | ||||||
|     title = youtube_tools.get_youtube_title(content) |  | ||||||
|     assert title == expect_title |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_check_exists(): |  | ||||||
|     expect_check = False |  | ||||||
|     # prerequisites for determining filename |  | ||||||
|     global file_name |  | ||||||
|     file_name = internals.sanitize_title(title) |  | ||||||
|     check = spotdl.check_exists(file_name, raw_song, meta_tags=None) |  | ||||||
|     assert check == expect_check |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_download(): |  | ||||||
|     expect_download = True |  | ||||||
|     download = youtube_tools.download_song(file_name, content) |  | ||||||
|     assert download == expect_download |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_convert(): |  | ||||||
|     # exit code 0 = success |  | ||||||
|     expect_converted = 0 |  | ||||||
|     global input_song |  | ||||||
|     global output_song |  | ||||||
|     input_song = file_name + const.args.input_ext |  | ||||||
|     output_song = file_name + const.args.output_ext |  | ||||||
|     converted = convert.song(input_song, output_song, const.args.folder) |  | ||||||
|     assert converted == expect_converted |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_metadata(): |  | ||||||
|     expect_metadata = None |  | ||||||
|     meta_tags = spotify_tools.generate_metadata(raw_song) |  | ||||||
|     if meta_tags: |  | ||||||
|         metadata_output = metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) |  | ||||||
|         metadata_input = metadata.embed(os.path.join(const.args.folder, input_song), meta_tags) |  | ||||||
|     else: |  | ||||||
|         metadata_input = None |  | ||||||
|         metadata_output = None |  | ||||||
|     assert (metadata_output == expect_metadata) and (metadata_input == expect_metadata) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_check_exists2(): |  | ||||||
|     expect_check = True |  | ||||||
|     os.remove(os.path.join(const.args.folder, input_song)) |  | ||||||
|     check = spotdl.check_exists(file_name, raw_song, meta_tags=None) |  | ||||||
|     os.remove(os.path.join(const.args.folder, output_song)) |  | ||||||
|     assert check == expect_check |  | ||||||
| @@ -1,84 +0,0 @@ | |||||||
|  |  | ||||||
| from core import const |  | ||||||
| from core import handle |  | ||||||
| from core import internals |  | ||||||
| from core import spotify_tools |  | ||||||
| from core import youtube_tools |  | ||||||
| from core import convert |  | ||||||
| from core import metadata |  | ||||||
|  |  | ||||||
| import spotdl |  | ||||||
|  |  | ||||||
| import loader |  | ||||||
| import os |  | ||||||
|  |  | ||||||
| loader.load_defaults() |  | ||||||
| internals.filter_path(const.args.folder) |  | ||||||
| raw_song = 'http://open.spotify.com/track/0JlS7BXXD07hRmevDnbPDU' |  | ||||||
|  |  | ||||||
| def test_spotify_title(): |  | ||||||
|     expect_title = 'David André Østby - Intro' |  | ||||||
|     global meta_tags |  | ||||||
|     meta_tags = spotify_tools.generate_metadata(raw_song) |  | ||||||
|     title = internals.generate_songname(const.args.file_format, meta_tags) |  | ||||||
|     assert title == expect_title |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_youtube_url(): |  | ||||||
|     expect_url = 'http://youtube.com/watch?v=rg1wfcty0BA' |  | ||||||
|     url = youtube_tools.generate_youtube_url(raw_song, meta_tags) |  | ||||||
|     assert url == expect_url |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_youtube_title(): |  | ||||||
|     expect_title = 'Intro - David André Østby' |  | ||||||
|     content = youtube_tools.go_pafy(raw_song, meta_tags) |  | ||||||
|     title = youtube_tools.get_youtube_title(content) |  | ||||||
|     assert title == expect_title |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_check_exists(): |  | ||||||
|     expect_check = False |  | ||||||
|     # prerequisites for determining filename |  | ||||||
|     songname = internals.generate_songname(const.args.file_format, meta_tags) |  | ||||||
|     global file_name |  | ||||||
|     file_name = internals.sanitize_title(songname) |  | ||||||
|     check = spotdl.check_exists(file_name, raw_song, meta_tags) |  | ||||||
|     assert check == expect_check |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_download(): |  | ||||||
|     expect_download = True |  | ||||||
|     # prerequisites for determining filename |  | ||||||
|     content = youtube_tools.go_pafy(raw_song, meta_tags) |  | ||||||
|     download = youtube_tools.download_song(file_name, content) |  | ||||||
|     assert download == expect_download |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_convert(): |  | ||||||
|     # exit code 0 = success |  | ||||||
|     expect_converted = 0 |  | ||||||
|     # prerequisites for determining filename |  | ||||||
|     global input_song |  | ||||||
|     global output_song |  | ||||||
|     input_song = file_name + const.args.input_ext |  | ||||||
|     output_song = file_name + const.args.output_ext |  | ||||||
|     converted = convert.song(input_song, output_song, const.args.folder) |  | ||||||
|     assert converted == expect_converted |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_metadata(): |  | ||||||
|     expect_metadata = True |  | ||||||
|     # prerequisites for determining filename |  | ||||||
|     metadata_output = metadata.embed(os.path.join(const.args.folder, output_song), meta_tags) |  | ||||||
|     metadata_input = metadata.embed(os.path.join(const.args.folder, input_song), meta_tags) |  | ||||||
|     assert metadata_output == (metadata_input == expect_metadata) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_check_exists2(): |  | ||||||
|     expect_check = True |  | ||||||
|     # prerequisites for determining filename |  | ||||||
|     os.remove(os.path.join(const.args.folder, input_song)) |  | ||||||
|     check = spotdl.check_exists(file_name, raw_song, meta_tags) |  | ||||||
|     os.remove(os.path.join(const.args.folder, output_song)) |  | ||||||
|     assert check == expect_check |  | ||||||
| @@ -1,55 +0,0 @@ | |||||||
| import spotdl |  | ||||||
|  |  | ||||||
| spotify = spotdl.spotify_tools.spotify |  | ||||||
| username = 'alex' |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_user(): |  | ||||||
|     expect_playlists = 7 |  | ||||||
|     playlists = spotify.user_playlists(username) |  | ||||||
|     playlists = len(playlists['items']) |  | ||||||
|     assert playlists == expect_playlists |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_playlist(): |  | ||||||
|     expect_tracks = 14 |  | ||||||
|     playlist = spotify.user_playlists(username)['items'][0] |  | ||||||
|     tracks = playlist['tracks']['total'] |  | ||||||
|     assert tracks == expect_tracks |  | ||||||
|  |  | ||||||
|  |  | ||||||
| def test_tracks(): |  | ||||||
|     playlist = spotify.user_playlists(username)['items'][0] |  | ||||||
|     expect_lines = playlist['tracks']['total'] |  | ||||||
|     result = spotify.user_playlist( |  | ||||||
|         playlist['owner']['id'], playlist['id'], fields='tracks,next') |  | ||||||
|     tracks = result['tracks'] |  | ||||||
|  |  | ||||||
|     with open('list.txt', 'w') as fout: |  | ||||||
|         while True: |  | ||||||
|             for item in tracks['items']: |  | ||||||
|                 track = item['track'] |  | ||||||
|                 try: |  | ||||||
|                     fout.write(track['external_urls']['spotify'] + '\n') |  | ||||||
|                 except KeyError: |  | ||||||
|                     pass |  | ||||||
|             # 1 page = 50 results |  | ||||||
|             # check if there are more pages |  | ||||||
|             if tracks['next']: |  | ||||||
|                 tracks = spotify.next(tracks) |  | ||||||
|             else: |  | ||||||
|                 break |  | ||||||
|  |  | ||||||
|     with open('list.txt', 'r') as listed: |  | ||||||
|         expect_song = (listed.read()).splitlines()[0] |  | ||||||
|  |  | ||||||
|     spotdl.internals.trim_song('list.txt') |  | ||||||
|     with open('list.txt', 'a') as myfile: |  | ||||||
|         myfile.write(expect_song) |  | ||||||
|  |  | ||||||
|     with open('list.txt', 'r') as listed: |  | ||||||
|         songs = (listed.read()).splitlines() |  | ||||||
|  |  | ||||||
|     lines = len(songs) |  | ||||||
|     song = songs[-1] |  | ||||||
|     assert (expect_lines == lines and expect_song == song) |  | ||||||
							
								
								
									
										133
									
								
								test/test_with_metadata.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										133
									
								
								test/test_with_metadata.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,133 @@ | |||||||
|  |  | ||||||
|  | from core import const | ||||||
|  | from core import internals | ||||||
|  | from core import spotify_tools | ||||||
|  | from core import youtube_tools | ||||||
|  | from core import convert | ||||||
|  | from core import metadata | ||||||
|  |  | ||||||
|  | import spotdl | ||||||
|  |  | ||||||
|  | import loader | ||||||
|  | import os | ||||||
|  |  | ||||||
|  | loader.load_defaults() | ||||||
|  | raw_song = 'http://open.spotify.com/track/0JlS7BXXD07hRmevDnbPDU' | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_metadata(): | ||||||
|  |     expect_number = 22 | ||||||
|  |     global meta_tags | ||||||
|  |     meta_tags = spotify_tools.generate_metadata(raw_song) | ||||||
|  |     assert len(meta_tags) == expect_number | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestFileFormat: | ||||||
|  |     def test_with_spaces(self): | ||||||
|  |         expect_title = 'David André Østby - Intro' | ||||||
|  |         title = internals.generate_songname(const.args.file_format, meta_tags) | ||||||
|  |         assert title == expect_title | ||||||
|  |  | ||||||
|  |     def test_without_spaces(self): | ||||||
|  |         expect_title = 'David_André_Østby_-_Intro' | ||||||
|  |         const.args.no_spaces = True | ||||||
|  |         title = internals.generate_songname(const.args.file_format, meta_tags) | ||||||
|  |         assert title == expect_title | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_youtube_url(): | ||||||
|  |     expect_url = 'http://youtube.com/watch?v=rg1wfcty0BA' | ||||||
|  |     url = youtube_tools.generate_youtube_url(raw_song, meta_tags) | ||||||
|  |     assert url == expect_url | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_youtube_title(): | ||||||
|  |     expect_title = 'Intro - David André Østby' | ||||||
|  |     global content | ||||||
|  |     content = youtube_tools.go_pafy(raw_song, meta_tags) | ||||||
|  |     title = youtube_tools.get_youtube_title(content) | ||||||
|  |     assert title == expect_title | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_check_exists(tmpdir): | ||||||
|  |     expect_check = False | ||||||
|  |     const.args.folder = str(tmpdir) | ||||||
|  |     # prerequisites for determining filename | ||||||
|  |     songname = internals.generate_songname(const.args.file_format, meta_tags) | ||||||
|  |     global file_name | ||||||
|  |     file_name = internals.sanitize_title(songname) | ||||||
|  |     check = spotdl.check_exists(file_name, raw_song, meta_tags) | ||||||
|  |     assert check == expect_check | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestDownload: | ||||||
|  |     def test_m4a(self): | ||||||
|  |         expect_download = True | ||||||
|  |         download = youtube_tools.download_song(file_name + '.m4a', content) | ||||||
|  |         assert download == expect_download | ||||||
|  |  | ||||||
|  |     def test_webm(self): | ||||||
|  |         expect_download = True | ||||||
|  |         download = youtube_tools.download_song(file_name + '.webm', content) | ||||||
|  |         assert download == expect_download | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestFFmpeg(): | ||||||
|  |     def test_convert_from_webm_to_mp3(self): | ||||||
|  |         expect_return_code = 0 | ||||||
|  |         return_code = convert.song(file_name + '.webm', | ||||||
|  |                                    file_name + '.mp3', | ||||||
|  |                                    const.args.folder) | ||||||
|  |         assert return_code == expect_return_code | ||||||
|  |  | ||||||
|  |     def test_convert_from_webm_to_m4a(self): | ||||||
|  |         expect_return_code = 0 | ||||||
|  |         return_code = convert.song(file_name + '.webm', | ||||||
|  |                                    file_name + '.m4a', | ||||||
|  |                                    const.args.folder) | ||||||
|  |         assert return_code == expect_return_code | ||||||
|  |  | ||||||
|  |  | ||||||
|  |     def test_convert_from_m4a_to_mp3(self): | ||||||
|  |         expect_return_code = 0 | ||||||
|  |         return_code = convert.song(file_name + '.m4a', | ||||||
|  |                                    file_name + '.mp3', | ||||||
|  |                                    const.args.folder) | ||||||
|  |         assert return_code == expect_return_code | ||||||
|  |  | ||||||
|  |     def test_convert_from_m4a_to_webm(self): | ||||||
|  |         expect_return_code = 0 | ||||||
|  |         return_code = convert.song(file_name + '.m4a', | ||||||
|  |                                    file_name + '.webm', | ||||||
|  |                                    const.args.folder) | ||||||
|  |         os.remove(os.path.join(const.args.folder, file_name + '.webm')) | ||||||
|  |         assert return_code == expect_return_code | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestAvconv: | ||||||
|  |     def test_convert_from_m4a_to_mp3(self): | ||||||
|  |         expect_return_code = 0 | ||||||
|  |         return_code = convert.song(file_name + '.m4a', | ||||||
|  |                                    file_name + '.mp3', | ||||||
|  |                                    const.args.folder, | ||||||
|  |                                    avconv=True) | ||||||
|  |         assert return_code == expect_return_code | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_embed_metadata(): | ||||||
|  |     expect_metadata = True | ||||||
|  |     # prerequisites for determining filename | ||||||
|  |     metadata_input = metadata.embed(os.path.join(const.args.folder, | ||||||
|  |                                                  file_name + '.m4a'), meta_tags) | ||||||
|  |     metadata_output = metadata.embed(os.path.join(const.args.folder, | ||||||
|  |                                                   file_name + '.mp3'), meta_tags) | ||||||
|  |     assert metadata_output == (metadata_input == expect_metadata) | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_check_exists2(): | ||||||
|  |     expect_check = True | ||||||
|  |     # prerequisites for determining filename | ||||||
|  |     os.remove(os.path.join(const.args.folder, file_name + '.m4a')) | ||||||
|  |     check = spotdl.check_exists(file_name, raw_song, meta_tags) | ||||||
|  |     os.remove(os.path.join(const.args.folder, file_name + '.mp3')) | ||||||
|  |     assert check == expect_check | ||||||
							
								
								
									
										87
									
								
								test/test_without_metadata.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								test/test_without_metadata.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | |||||||
|  | from core import const | ||||||
|  | from core import internals | ||||||
|  | from core import spotify_tools | ||||||
|  | from core import youtube_tools | ||||||
|  |  | ||||||
|  | import spotdl | ||||||
|  | import loader | ||||||
|  |  | ||||||
|  | import os | ||||||
|  | import builtins | ||||||
|  |  | ||||||
|  | loader.load_defaults() | ||||||
|  | raw_song = "Tony's Videos VERY SHORT VIDEO 28.10.2016" | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_metadata(): | ||||||
|  |     expect_metadata = None | ||||||
|  |     global metadata | ||||||
|  |     metadata = spotify_tools.generate_metadata(raw_song) | ||||||
|  |     assert metadata == expect_metadata | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestYouTubeURL: | ||||||
|  |     def test_only_music_category(self): | ||||||
|  |         expect_url = 'http://youtube.com/watch?v=P11ou3CXKZo' | ||||||
|  |         const.args.music_videos_only = True | ||||||
|  |         url = youtube_tools.generate_youtube_url(raw_song, metadata) | ||||||
|  |         assert url == expect_url | ||||||
|  |  | ||||||
|  |     def test_all_categories(self): | ||||||
|  |         expect_url = 'http://youtube.com/watch?v=qOOcy2-tmbk' | ||||||
|  |         const.args.music_videos_only = False | ||||||
|  |         url = youtube_tools.generate_youtube_url(raw_song, metadata) | ||||||
|  |         assert url == expect_url | ||||||
|  |  | ||||||
|  |     def test_args_manual(self, monkeypatch): | ||||||
|  |         expect_url = 'http://youtube.com/watch?v=qOOcy2-tmbk' | ||||||
|  |         const.args.manual = True | ||||||
|  |         monkeypatch.setattr('builtins.input', lambda x: '1') | ||||||
|  |         url = youtube_tools.generate_youtube_url(raw_song, metadata) | ||||||
|  |         assert url == expect_url | ||||||
|  |  | ||||||
|  |     def test_args_manual_none(self, monkeypatch): | ||||||
|  |         expect_url = None | ||||||
|  |         monkeypatch.setattr('builtins.input', lambda x: '0') | ||||||
|  |         url = youtube_tools.generate_youtube_url(raw_song, metadata) | ||||||
|  |         const.args.manual = False | ||||||
|  |         assert url == expect_url | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestYouTubeTitle: | ||||||
|  |     def test_single_download(self): | ||||||
|  |         global content | ||||||
|  |         global title | ||||||
|  |         expect_title = "Tony's Videos VERY SHORT VIDEO 28.10.2016" | ||||||
|  |         content = youtube_tools.go_pafy(raw_song, metadata) | ||||||
|  |         title = youtube_tools.get_youtube_title(content) | ||||||
|  |         assert title == expect_title | ||||||
|  |  | ||||||
|  |     def test_download_from_list(self): | ||||||
|  |         expect_title = "1. Tony's Videos VERY SHORT VIDEO 28.10.2016" | ||||||
|  |         content = youtube_tools.go_pafy(raw_song, metadata) | ||||||
|  |         title = youtube_tools.get_youtube_title(content, 1) | ||||||
|  |         assert title == expect_title | ||||||
|  |  | ||||||
|  |  | ||||||
|  | def test_check_exists(tmpdir): | ||||||
|  |     expect_check = False | ||||||
|  |     const.args.folder = str(tmpdir) | ||||||
|  |     # prerequisites for determining filename | ||||||
|  |     global file_name | ||||||
|  |     file_name = internals.sanitize_title(title) | ||||||
|  |     check = spotdl.check_exists(file_name, raw_song, metadata) | ||||||
|  |     assert check == expect_check | ||||||
|  |  | ||||||
|  |  | ||||||
|  | class TestDownload: | ||||||
|  |     def test_webm(self): | ||||||
|  |         # content does not have any .webm audiostream | ||||||
|  |         expect_download = False | ||||||
|  |         download = youtube_tools.download_song(file_name + '.webm', content) | ||||||
|  |         assert download == expect_download | ||||||
|  |  | ||||||
|  |     def test_other(self): | ||||||
|  |         expect_download = False | ||||||
|  |         download = youtube_tools.download_song(file_name + '.fake_extension', content) | ||||||
|  |         assert download == expect_download | ||||||
		Reference in New Issue
	
	Block a user