songs2slides

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

commit 64a761a4afb401ec4c359d01e5134b6dc3644b19
parent 64b894a78cbdad2299f35825da224e196bc1afeb
Author: Asher Morgan <59518073+ashermorgan@users.noreply.github.com>
Date:   Mon,  8 Apr 2024 18:51:05 -0700

Implement API_AUTH environment variable

Diffstat:
MREADME.md | 3++-
Msongs2slides/core.py | 10+++++++++-
Mtests/test_core.py | 57++++++++++++++++++++++++++++++++++++++++++++++++++++-----
3 files changed, 63 insertions(+), 7 deletions(-)

diff --git a/README.md b/README.md @@ -9,7 +9,8 @@ python3 -m pip install -r requirements.txt 2. Add variables to `.env` file ``` -API_URL="http://exampl.com/get-lyrics?title={title}&artist={artist}" +API_URL="http://example.com/get-lyrics?title={title}&artist={artist}" +API_AUTH="Bearer secrettoken" # Optional ``` 3. Run app in debug mode diff --git a/songs2slides/core.py b/songs2slides/core.py @@ -72,13 +72,21 @@ def get_song_data(title: str, artist:str): The song data """ + # Get API URL 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() + # Get HTTP authorization header + auth = os.getenv('API_AUTH', None) + headers = { 'Authorization': auth } if auth else {} + + # Query API + data = requests.get(url, headers=headers).json() + + # Parse response if 'lyrics' in data.keys(): return SongData(data['title'], data['artist'], filter_lyrics(data['lyrics'])) diff --git a/tests/test_core.py b/tests/test_core.py @@ -72,7 +72,10 @@ class TestCore(unittest.TestCase): patch('songs2slides.core.filter_lyrics') as mocked_clean: # Mock os.getenv, requests.get, and core.filter_lyrics - mocked_env.return_value = 'api://lyrics/{artist}/{title}' + mocked_env.side_effect = [ + 'api://lyrics/{artist}/{title}', + 'Bearer secrettoken' + ] mocked_get.return_value.json.return_value = { 'lyrics': 'raw', 'title': 'Foo', @@ -85,8 +88,47 @@ class TestCore(unittest.TestCase): song_data = core.get_song_data('foo', 'bar') # Assert mocked methods were used correctly - mocked_env.assert_called_with('API_URL') - mocked_get.assert_called_with('api://lyrics/bar/foo') + mocked_env.assert_has_calls([ + call('API_URL'), + call('API_AUTH', None) + ]) + mocked_get.assert_called_with('api://lyrics/bar/foo', headers={ + 'Authorization': 'Bearer secrettoken' + }) + mocked_clean.assert_called_with('raw') + + # Assert song data is correct + self.assertEqual(song_data.title, 'Foo') + self.assertEqual(song_data.artist, 'Bar') + self.assertEqual(song_data.lyrics, 'clean') + + def test_get_song_data_no_auth_header(self): + with patch('songs2slides.core.os.getenv') as mocked_env, \ + patch('songs2slides.core.requests.get') as mocked_get, \ + patch('songs2slides.core.filter_lyrics') as mocked_clean: + + # Mock os.getenv, requests.get, and core.filter_lyrics + mocked_env.side_effect = [ + 'api://lyrics/{artist}/{title}', + None, + ] + mocked_get.return_value.json.return_value = { + 'lyrics': 'raw', + 'title': 'Foo', + 'artist': 'Bar', + } + mocked_get.return_value.status_code = 200 + mocked_clean.return_value = 'clean' + + # Get song data + song_data = core.get_song_data('foo', 'bar') + + # Assert mocked methods were used correctly + mocked_env.assert_has_calls([ + call('API_URL'), + call('API_AUTH', None) + ]) + mocked_get.assert_called_with('api://lyrics/bar/foo', headers={}) mocked_clean.assert_called_with('raw') # Assert song data is correct @@ -115,7 +157,10 @@ class TestCore(unittest.TestCase): patch('songs2slides.core.requests.get') as mocked_get: # Mock os.getenv and requests.get - mocked_env.return_value = 'api://lyrics/{artist}/{title}' + mocked_env.side_effect = [ + 'api://lyrics/{artist}/{title}', + 'Bearer secrettoken' + ] mocked_get.return_value.text = b'{}' mocked_get.return_value.status_code = 200 @@ -124,7 +169,9 @@ class TestCore(unittest.TestCase): song_data = core.get_song_data('foo', 'bar') # Assert request was called - mocked_get.assert_called_with('api://lyrics/bar/foo') + mocked_get.assert_called_with('api://lyrics/bar/foo', headers={ + 'Authorization': 'Bearer secrettoken' + }) def test_parse_song_lyrics_basic(self): # Declare song data and expected slides