Source code for app.utils
from .env import convert
from flask import request
[docs]class Lyrics(object):
"""
Data model for a song's lyrics.
:attr sections: A key-value pairing of section to lyrics.
"""
def __init__(self):
self.sections = dict()
[docs] def add_section(self, section, lyrics):
"""
Adds a section to the Lyrics object.
:param section: The name of the section. (e.g. `V1`, `A`, `Chorus`
etc.)
:type section: `str`
:param lyrics: The lyrics of that section.
:type lyrics: `str`
"""
self.sections[section] = lyrics
[docs] def to_dict(self):
"""
:returns: a `dict` representation of the Lyrics object.
"""
return self.sections
[docs]def get_lyrics(request: request, exclude_id: int=None):
"""
Utility function that returns a Lyrics object containing the song lyrics.
:param request: `request` object from the Flask app.
:param exclude_id: an integer identifying which lyrics section to exclude.
:returns: A Lyrics object containing the song's lyrics in a structured
format.
"""
# Defensive programming checks
if exclude_id:
assert isinstance(exclude_id, int)
# Get lyrics
lyr = Lyrics()
for k, v in request.form.items():
if "section-" in k:
idx = int(k.split("-")[-1])
if idx is not exclude_id:
# First, convert to traditional.
lyrics = convert(request.form[f"lyrics-{idx}"])
section = request.form[k]
lyr.add_section(section=section, lyrics=lyrics)
return lyr
[docs]def clean_lyrics(song):
"""
Cleans the lyrics in a song object.
"""
cleaned_lyrics = dict()
for name, lyrics in song.lyrics.items():
# Strip trailing punctuation except for question marks.
lyrics = lyrics.strip("。,;:").strip(',.;:')
# Replace middle punctuation with special blank-space character.
# The special space character is specified here:
# https://unicodelookup.com/#%E3%80%80/1
lyrics = (
lyrics.replace("。", " ")
.replace(",", " ")
.replace(";", " ")
.replace("、", " ")
.replace(".", " ")
.replace(",", " ")
.replace(";", " ")
.replace(" ", " ")
)
cleaned_lyrics[name] = lyrics
song.lyrics.update(cleaned_lyrics)
return song
[docs]def clean_arrangement(arrangement):
"""
Cleans the song arrangement and turns it into a list.
:example:
>>> str_arr = 'V, C, V, C'
>>> clean_arrangement(str_arr)
['V', 'C', 'V', 'C']
:param arrangement: a comma-delimited string containing the arrangement of
the song.
:type arrangement: `str`
:param song_data: a data dictionary. Keys are the data model fields as
specified in `datamodels.py`. One of the keys has to be "lyrics".
:type song_data: `dict`
:returns: arrangement a list of strings, each of which is a key in song's
lyrics dictionary.
:rtype: `list(str)`
"""
arrangement = [a.strip(" ") for a in arrangement.split(",")]
return arrangement
[docs]def allowed_file(filename):
"""
Utility function that checks that the filename has an allowed extension.
Used when uploading the file. Checks the module-level variable
`ALLOWED_EXTENSIONS` for allowed uploads.
:param filename: The name of the file that is being uploaded.
:type filename: `str`
:example:
>>> ALLOWED_EXTENSIONS = ['.pdf', '.jpg'] # module-level variable
>>> file1 = 'my_file.txt'
>>> allowed_file(file1)
False
>>> file2 = 'my_file'
>>> allowed_file(file2)
False
>>> file3 = 'my_file.jpg'
>>> allowed_file(file3)
True
"""
ALLOWED_EXTENSIONS = set(["pdf"])
return (
"." in filename
and filename.rsplit(".", 1)[1].lower() in ALLOWED_EXTENSIONS
)
[docs]def lyrics_plaintext(song):
"""
Get lyrics as plaintext.
"""
output = ""
song = validate_song(song)
output += song.default_arrangement
output += "\n\n\n\n"
output += song.composer
output += "\n"
output += song.copyright
output += "\n\n"
for section, lyrics in song.lyrics.items():
output += section
output += "\n"
output += lyrics
output += "\n\n"
return output
[docs]def validate_song(song):
"""
Converts song fields from None to '' for string outputs.
"""
attrs = ["default_arrangement", "composer", "copyright", "youtube", "ccli"]
for a in attrs:
if getattr(song, a) in [None, "None"]:
setattr(song, a, "")
return song