commit 2b6f2c24ce026d93da8a4bc3240943c214f1990d
parent ef8792327da870747c9cb569543a18d8e47b0fdc
Author: ashermorgan <59518073+ashermorgan@users.noreply.github.com>
Date: Fri, 23 Feb 2024 09:04:13 -0800
Implement filter_lyrics function
Diffstat:
2 files changed, 105 insertions(+), 7 deletions(-)
diff --git a/songs2slides/core.py b/songs2slides/core.py
@@ -5,6 +5,7 @@ from pptx.dml.color import RGBColor
from pptx.enum.text import MSO_ANCHOR, PP_ALIGN
from pptx.util import Inches, Pt
import os
+import re
import requests
@dataclass
@@ -26,6 +27,35 @@ class SongData:
artist: str
lyrics: str
+def filter_lyrics(lyrics: str):
+ """
+ Filter raw lyrics to remove text enclosed in brackets or parenthesis
+
+ Used by get_song_data
+
+ Parameters
+ ----------
+ lyrics : str
+ The raw lyrics
+
+ Returns
+ -------
+ str
+ The filtered lyrics
+ """
+
+ filtered = '\n' + lyrics + '\n'
+
+ # Remove enclosed text that takes up whole numbers of lines
+ filtered = re.sub(r'\n\[[^\]]*\]\n', '\n', filtered)
+ filtered = re.sub(r'\n\([^\)]*\)\n', '\n', filtered)
+
+ # Remove enclosed text that takes up partial lines
+ filtered = re.sub(r'\[[^\]]*\]', '', filtered)
+ filtered = re.sub(r'\([^\)]*\)', '', filtered)
+
+ return filtered.strip()
+
def get_song_data(title: str, artist:str):
"""
Get song data from an external API
@@ -51,7 +81,8 @@ def get_song_data(title: str, artist:str):
data = requests.get(url).json()
if 'lyrics' in data.keys():
- return SongData(data['title'], data['artist'], data['lyrics'])
+ return SongData(data['title'], data['artist'],
+ filter_lyrics(data['lyrics']))
else:
raise Exception()
diff --git a/tests/test_core.py b/tests/test_core.py
@@ -4,28 +4,95 @@ from unittest.mock import patch, call
from songs2slides import core
class TestCore(unittest.TestCase):
+ def test_filter_lyrics_inline(self):
+ # Declare raw lyrics and expected cleaned lyrics
+ lyrics = 'A[remove]B\nC(remove)D'
+ expected = 'AB\nCD'
+
+ # Clean lyrics
+ result = core.filter_lyrics(lyrics)
+
+ # Assert slides are correct
+ self.assertEqual(result, expected)
+
+ def test_filter_lyrics_whole_lines(self):
+ # Declare raw lyrics and expected cleaned lyrics
+ lyrics = 'A\n[remove]\nB\n(remove)\nC'
+ expected = 'A\nB\nC'
+
+ # Clean lyrics
+ result = core.filter_lyrics(lyrics)
+
+ # Assert slides are correct
+ self.assertEqual(result, expected)
+
+ def test_filter_lyrics_multiple_lines(self):
+ # Declare raw lyrics and expected cleaned lyrics
+ lyrics = 'A\n[re\nmove]\nB\n(re\nmove)\nC'
+ expected = 'A\nB\nC'
+
+ # Clean lyrics
+ result = core.filter_lyrics(lyrics)
+
+ # Assert slides are correct
+ self.assertEqual(result, expected)
+
+ def test_filter_lyrics_blank_lines(self):
+ # Declare raw lyrics and expected cleaned lyrics
+ lyrics = 'A\n[remove]\n\n(remove)\nB'
+ expected = 'A\n\nB'
+
+ # Clean lyrics
+ result = core.filter_lyrics(lyrics)
+
+ # Assert slides are correct
+ self.assertEqual(result, expected)
+
+ def test_filter_lyrics_all(self):
+ # Declare raw lyrics and expected cleaned lyrics
+ lyrics = 'A[remove]B\n[remove]\n\nC(remove)D\n(re\nmove)'
+ expected = 'AB\n\nCD'
+
+ # Clean lyrics
+ result = core.filter_lyrics(lyrics)
+
+ # Assert slides are correct
+ self.assertEqual(result, expected)
+
+ def test_filter_lyrics_empty_string(self):
+ # Clean lyrics
+ result = core.filter_lyrics('')
+
+ # Assert slides are correct
+ self.assertEqual(result, '')
+
def test_get_song_data_success(self):
with patch('songs2slides.core.os.getenv') as mocked_env, \
- patch('songs2slides.core.requests.get') as mocked_get:
+ patch('songs2slides.core.requests.get') as mocked_get, \
+ patch('songs2slides.core.filter_lyrics') as mocked_clean:
- # Mock os.getenv and requests.get
+ # Mock os.getenv, requests.get, and core.filter_lyrics
mocked_env.return_value = 'api://lyrics/{artist}/{title}'
- mocked_get.return_value.text = b'{"lyrics":"A\nB\nC\nD","title":"Foo","artist":"Bar","image":null}'
mocked_get.return_value.json.return_value = {
- 'lyrics': 'A\nB\nC\nD',
+ '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 song data is correct
+ # Assert mocked methods were used correctly
+ mocked_env.assert_called_with('API_URL')
mocked_get.assert_called_with('api://lyrics/bar/foo')
+ 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, 'A\nB\nC\nD')
+ self.assertEqual(song_data.lyrics, 'clean')
def test_get_song_data_no_url(self):
with patch('songs2slides.core.os.getenv') as mocked_env, \