Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
def test_artist(self):
msg = "The returned object is not an instance of the Artist class."
self.assertIsInstance(self.artist, Artist, msg)
def test_song(self):
msg = "The returned object is not an instance of the Song class."
self.assertIsInstance(self.song, Song, msg)
def determine_filenames(self, extension):
expected_filenames = []
for song in self.artist.songs:
fn = "lyrics_{name}_{song}.{ext}".format(name=self.artist.name,
song=song.title,
ext=extension)
fn = sanitize_filename(fn.lower().replace(" ", ""))
expected_filenames.append(fn)
return expected_filenames
import os
import unittest
from lyricsgenius.api import Genius
from lyricsgenius.song import Song
from lyricsgenius.artist import Artist
from lyricsgenius.utils import sanitize_filename
# Import client access token from environment variable
client_access_token = os.environ.get("GENIUS_CLIENT_ACCESS_TOKEN", None)
assert client_access_token is not None, "Must declare environment variable: GENIUS_CLIENT_ACCESS_TOKEN"
genius = Genius(client_access_token, sleep_time=0.5)
class TestEndpoints(unittest.TestCase):
@classmethod
def setUpClass(cls):
print("\n---------------------\nSetting up Endpoint tests...\n")
cls.search_term = "Ezra Furman"
cls.song_title_only = "99 Problems"
def test_search_genius_web(self):
# TODO: test more than just a 200 response
msg = "Response was None."
r = genius.search_genius_web(self.search_term)
self.assertTrue(r is not None, msg)
if self.verbose:
print("Found alternate name. Changing name to {}.".format(json_artist['name']))
artist_name = json_artist['name']
break
artist_id = None
if first_result is not None and artist_id is None and self.verbose:
if input("Couldn't find {}. Did you mean {}? (y/n): ".format(artist_name,
first_result['name'])).lower() == 'y':
artist_name, artist_id = first_result['name'], first_result['id']
assert (not isinstance(artist_id, type(None))), "Could not find artist. Check spelling?"
# Make Genius API request for the determined artist ID
json_artist = self.get_artist(artist_id)
# Create the Artist object
artist = Artist(json_artist)
if max_songs is None or max_songs > 0:
# Access the api_path found by searching
artist_search_results = self.get_artist_songs(artist_id)
# Download each song by artist, store as Song objects in Artist object
keep_searching = True
next_page, n = 0, 0
while keep_searching:
for json_song in artist_search_results['songs']:
# TODO: Shouldn't I use self.search_song() here?
# Songs must have a title
if 'title' not in json_song:
json_song['title'] = 'MISSING TITLE'
return found_artist['id']
# Get the artist ID (or use the one supplied)
artist_id = artist_id if artist_id else find_artist_id(artist_name)
if artist_id == None:
return None
artist_info = self.get_artist(artist_id)
found_name = artist_info['artist']['name']
if found_name != artist_name and allow_name_change:
if self.verbose:
print("Changing artist name to '{a}'".format(a=found_name))
artist_name = found_name
# Create the Artist object
artist = Artist(artist_info)
# Download each song by artist, stored as Song objects in Artist object
page = 1
reached_max_songs = False
while not reached_max_songs:
songs_on_page = self.get_artist_songs(artist_id, sort, per_page, page)
# Loop through each song on page of search results
for song_info in songs_on_page['songs']:
# Check if song is valid (e.g. has title, contains lyrics)
has_title = ('title' in song_info)
has_lyrics = self._result_is_lyrics(song_info['title'])
valid = has_title and (has_lyrics or (not self.skip_non_songs))
# Reject non-song results (e.g. Linear Notes, Tracklists, etc.)
if not valid:
def save_artists(self, artists, filename="artist_lyrics", overwrite=False):
"""Save lyrics from multiple Artist objects as JSON object
:param artists: List of Artist objects to save lyrics from
:param filename: Name of output file (json)
:param overwrite: Overwrites preexisting file if True
"""
if isinstance(artists, Artist):
artists = [artists]
# Create a temporary directory for lyrics
start = time.time()
tmp_dir = 'tmp_lyrics'
if not os.path.isdir(tmp_dir):
os.mkdir(tmp_dir)
count = 0
else:
count = len(os.listdir(tmp_dir))
# Check if file already exists
if os.path.isfile(filename + ".json") and not overwrite:
msg = "{f} already exists. Overwrite?\n(y/n): ".format(f=filename)
if input(msg).lower() != "y":
print("Leaving file in place. Exiting.")
# Check if file already exists
if not os.path.isfile(filename + ".json"):
pass
elif overwrite:
pass
else:
if input("{} already exists. Overwrite?\n(y/n): ".format(filename)).lower() != 'y':
print("Leaving file in place. Exiting.")
os.rmdir(tmp_dir)
return
# Extract each artist's lyrics in json format
all_lyrics = {'artists': []}
for n, artist in enumerate(artists):
if isinstance(artist, Artist):
all_lyrics['artists'].append({})
tmp_file = "." + os.sep + tmp_dir + os.sep + "tmp_{num}_{name}".format(num=(n + tmp_count),
name=artist.name.replace(" ", ""))
print(tmp_file)
all_lyrics['artists'][-1] = artist.save_lyrics(filename=tmp_file,
overwrite=True)
else:
warn("Item #{} was not of type Artist. Skipping.".format(n))
# Save all of the lyrics
with open(filename + '.json', 'w') as outfile:
json.dump(all_lyrics, outfile)
end = time.time()
print("Time elapsed: {} hours".format((end-start)/60.0/60.0))
# TODO: Shouldn't I use self.search_song() here?
# Songs must have a title
if 'title' not in json_song:
json_song['title'] = 'MISSING TITLE'
# Remove non-song results (e.g. Linear Notes, Tracklists, etc.)
song_is_valid = self._result_is_lyrics(json_song['title']) if self.skip_non_songs else True
if song_is_valid:
# Scrape song lyrics from the song's HTML
lyrics = self._scrape_song_lyrics_from_url(json_song['url'])
# Create song object for current song
if get_full_song_info:
song = Song(self.get_song(json_song['id']), lyrics)
else:
# Create song with less info (faster)
song = Song({'song': json_song}, lyrics)
# Add song to the Artist object
if artist.add_song(song, verbose=False) == 0:
n += 1
if self.verbose:
print('Song {0}: "{1}"'.format(n, song.title))
else: # Song does not contain lyrics
if self.verbose:
print('"{title}" does not contain lyrics. Rejecting.'.format(title=json_song['title']))
# Check if user specified a max number of songs
if not isinstance(max_songs, type(None)):
valid = has_title and (has_lyrics or (not self.skip_non_songs))
# Reject non-song results (e.g. Linear Notes, Tracklists, etc.)
if not valid:
if self.verbose:
s = song_info['title'] if has_title else "MISSING TITLE"
print('"{s}" is not valid. Skipping.'.format(s=s))
continue
# Create the Song object from lyrics and metadata
lyrics = self._scrape_song_lyrics_from_url(song_info['url'])
if get_full_info:
info = self.get_song(song_info['id'])
else:
info = {'song': song_info}
song = Song(info, lyrics)
# Attempt to add the Song to the Artist
result = artist.add_song(song, verbose=False)
if result == 0 and self.verbose:
print('Song {n}: "{t}"'.format(n=artist.num_songs,
t=song.title))
# Exit search if the max number of songs has been met
reached_max_songs = max_songs and artist.num_songs >= max_songs
if reached_max_songs:
if self.verbose:
print('\nReached user-specified song limit ({m}).'.format(m=max_songs))
break
# Move on to next page of search results
page = songs_on_page['next_page']