songs2slides

A tool that automatically finds song lyrics and creates lyric slideshows
git clone https://git.ashermorgan.net/songs2slides/
Log | Files | Refs | README

commit 600f02e3c109462ae6655fe0344dcb0541c3f21a
parent 070a73a9c03f377a248c60afcd7a8ee7123924f0
Author: ashermorgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Mon, 19 Feb 2024 17:45:00 -0800

Implement get_song_data function

Diffstat:
Mrequirements.txt | 2++
Asongs2slides/utils.py | 52++++++++++++++++++++++++++++++++++++++++++++++++++++
Crequirements.txt -> tests/__init__.py | 0
Atests/test_core.py | 60++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 114 insertions(+), 0 deletions(-)

diff --git a/requirements.txt b/requirements.txt @@ -0,0 +1,2 @@ +python-dotenv +requests diff --git a/songs2slides/utils.py b/songs2slides/utils.py @@ -0,0 +1,52 @@ +from dotenv import load_dotenv + +import os +import requests + +class SongData: + """ + Represents data about a song + + Attributes: + ----------- + title : str + The title of the song + artist : str + The artist of the song + lyrics : str + The song's lyrics, with double newlines separating stanzas + """ + + def __init__(self, title: str, artist: str, lyrics: str): + self.title = title + self.artist = artist + self.lyrics = lyrics + +def get_song_data(title: str, artist:str): + """ + Get song data from an external API + + Parameters: + ----------- + title : str + The title of the song + artist : str + The artist of the song + + Returns + ------- + SongData + The song data + """ + + url = os.getenv('API_URL') + if url is None: + raise Exception() + url = url.replace('{title}', title, 1) + url = url.replace('{artist}', artist, 1) + data = requests.get(url).json() + + if 'lyrics' in data.keys(): + return SongData(data['title'], data['artist'], data['lyrics']) + else: + raise Exception() diff --git a/requirements.txt b/tests/__init__.py diff --git a/tests/test_core.py b/tests/test_core.py @@ -0,0 +1,60 @@ +import unittest +from unittest.mock import patch + +from songs2slides import utils + +class TestUtils(unittest.TestCase): + def test_get_song_data_success(self): + with patch('songs2slides.utils.os.getenv') as mocked_env, \ + patch('songs2slides.utils.requests.get') as mocked_get: + + # Mock os.getenv and requests.get + mocked_env.return_value = 'api://lyrics/{artist}/{title}' + mocked_get.return_value.text = b'{"lyrics":"Test1\nTest2\nTest3\nTest4","title":"Foo","artist":"Bar","image":null}' + mocked_get.return_value.json.return_value = { + 'lyrics': 'Test1\nTest2\nTest3\nTest4', + 'title': 'Foo', + 'artist': 'Bar', + } + mocked_get.return_value.status_code = 200 + + # Get song data + song_data = utils.get_song_data('foo', 'bar') + + # Assert song data is correct + mocked_get.assert_called_with('api://lyrics/bar/foo') + self.assertEqual(song_data.title, 'Foo') + self.assertEqual(song_data.artist, 'Bar') + self.assertEqual(song_data.lyrics, 'Test1\nTest2\nTest3\nTest4') + + def test_get_song_data_no_url(self): + with patch('songs2slides.utils.os.getenv') as mocked_env, \ + patch('songs2slides.utils.requests.get') as mocked_get: + + # Mock os.getenv and requests.get + mocked_env.return_value = None + mocked_get.return_value.text = b'{}' + mocked_get.return_value.status_code = 200 + + # Try to get song data + with self.assertRaises(Exception): + song_data = utils.get_song_data('foo', 'bar') + + # Assert request was not called + mocked_get.assert_not_called() + + def test_get_song_data_not_found(self): + with patch('songs2slides.utils.os.getenv') as mocked_env, \ + patch('songs2slides.utils.requests.get') as mocked_get: + + # Mock os.getenv and requests.get + mocked_env.return_value = 'api://lyrics/{artist}/{title}' + mocked_get.return_value.text = b'{}' + mocked_get.return_value.status_code = 200 + + # Try to get song data + with self.assertRaises(Exception): + song_data = utils.get_song_data('foo', 'bar') + + # Assert request was called + mocked_get.assert_called_with('api://lyrics/bar/foo')