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:
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