From bc4e7ed51dee1739b1e8ad74538ce21936cf8dee Mon Sep 17 00:00:00 2001 From: Carlos Galindo Date: Fri, 8 Sep 2023 12:15:30 +0200 Subject: [PATCH] documentacion y pistas de tipo en metodos --- src/audio_scanner.py | 4 +- src/create_songbook.py | 2 + src/latex_scanner.py | 86 ++++++++++++++++++++++++++++++------------ src/model.py | 3 +- 4 files changed, 67 insertions(+), 28 deletions(-) diff --git a/src/audio_scanner.py b/src/audio_scanner.py index d798cd5..9a5c728 100644 --- a/src/audio_scanner.py +++ b/src/audio_scanner.py @@ -1,8 +1,8 @@ +import re from os import listdir from os.path import isfile, join -from model import Audio -import re from datetime import datetime +from model import Audio def find_audios(index, audio_dir): diff --git a/src/create_songbook.py b/src/create_songbook.py index 68e90c4..edc2308 100644 --- a/src/create_songbook.py +++ b/src/create_songbook.py @@ -6,6 +6,7 @@ import pickle def generate_songbook(songs, song_numbers, out_file, dj_engine): + '''Generate an HTML file with a sequence of songs.''' # Build the list of songs song_list = [] for n in song_numbers: @@ -24,6 +25,7 @@ def generate_songbook(songs, song_numbers, out_file, dj_engine): def create_argparser(): + '''Parse main's arguments.''' parser = latex_scanner.create_argparser() parser.add_argument("--songs", required=True, nargs='+', type=int, help="A list of song numbers to include.") parser.add_argument("--output-file", required=False, nargs=1, default=["misa.html"], diff --git a/src/latex_scanner.py b/src/latex_scanner.py index 6855ecf..41926b4 100644 --- a/src/latex_scanner.py +++ b/src/latex_scanner.py @@ -11,7 +11,7 @@ from audio_scanner import find_audios from model import Chord, Line, Song, Verse -def mkdir(path): +def mkdir(path: str) -> None: if not os.path.exists(path): os.mkdir(path) @@ -19,33 +19,40 @@ def mkdir(path): # Note that re.match prepends ^ to the pattern, whereas re.search doesn't -def read_property(text, key): +def read_property(text: str, key: str) -> str | None: + '''A parser for \\beginsong attributes.''' if text is None: return None match = re.search(key + "={(.*?)}", text) return match.group(1) if match else None -def extra_put(extra, index, the_type, data=None): +def extra_put(extra: list, index: int, the_type: str, data: dict|None = None): + '''Adds the given data (if any) to the extra list, \ + at the given index, and tagged with the given the_type.''' payload = {'type': the_type, 'data': data} if data else {'type': the_type} if index not in extra: - extra[index] = [] + extra[index] = [] extra[index].append(payload) class SongLoader: - def __init__(self, latex_file, audio_dir=None): - self.index = 1 - self.category = None - self.categories = [] - self.songs = [] + '''Parses LaTeX files to build a collection of song objects.''' + + def __init__(self, latex_file: str, audio_dir: str | None = None): + '''Initializes and populates a LaTeX reader.''' + self.index: int = 1 + self.category: str | None = None + self.categories: list[str] = [] + self.songs: list[Song] = [] if audio_dir: self.audio_dir = audio_dir self.scan(latex_file) - def scan(self, latex_file): + def scan(self, latex_file: str) -> None: + '''Reads through an index file and scans each song, with the same numbers. + :param latex_file: The main latex file, which includes songs via \\input.''' main_file = open(latex_file, 'r') - canciones_dir = join(str(Path(latex_file).parent), "canciones") for line in main_file.readlines(): # Remove newline if line[-1] == '\n': @@ -61,14 +68,18 @@ class SongLoader: self.category = re_chapter_match.group(1) self.categories.append(self.category) # Traverse into \input commands if path starts w/ 'canciones/' - re_input_match = re.search(r"\\input{canciones/(.*?)}", line) + re_input_match = re.search(r"\\input{(.*?)}", line) if re_input_match is not None: - input_file = join(canciones_dir, re_input_match.group(1)) + input_file = join(str(Path(latex_file).parent), re_input_match.group(1)) if not input_file.endswith(".tex"): input_file += ".tex" self.scan_song_file(input_file) - def scan_others(self, folder, start_index): + def scan_others(self, folder: str, start_index: int) -> None: + '''Looks for songs not found during self.scan(...). + :param folder: A folder to scan through, looking for .tex files. + :param start_index: When numbering new songs, the first index to use. + ''' self.index = start_index self.category = "Nuevas" self.categories.append(self.category) @@ -81,22 +92,46 @@ class SongLoader: print("Scanning extra file", f) self.scan_song_file(f) - def scan_song_file(self, song_file): + def scan_song_file(self, song_file: str) -> None: + '''Scan a single song file and store any songs found.''' # Variables - ignore = False - current_song = None - current_verse = None - memory = None - memorizing = False - replay_index = 0 - transpose = 0 - trfmt = "normal" + ignore: bool = False + current_song: Song | None = None + current_verse: Verse | None = None + memory: str | None = None + memorizing: bool = False + replay_index: int = 0 + transpose: int = 0 + trfmt: str = "normal" + # General behaviour: read the file and scan line-by-line + # In each line, read char-by-char, searching for common LaTeX commands + # Apply the effects of these commands, and add each verse (line inside + # song after removing all commands) to build up each song. + # Commands include: + ### Comments: % Something something -> Ignored + ### Line break locations: \brk -> Ignored + ### Transpose: \transpose{SEMITONES} + ### Begin song: \beginsong{NAME}[METADATA] + ### End song: \endsong + ### Verse begin/end: \beginverse, \endverse + ### Chorus begin/end: \beginchorus, \endchorus + ### Capo: \capo{FRET} + ### Chord-excl. txt.: \ifchorded, \else, \fi + ### (the contents between \else and \fi are discarded) + ### Echoes: \echo{TEXT} + ### Chord: \[CHORD] + ### Chord repetition: \^ + ### Music repetition: \lrep, \rrep + ### Lyric repetition: \rep{TIMES} + ### Chord memory: \memorize, \replay + ### Transpose format: \renewcommand{\trchordformat}[2]{.*} + ### Other unrecognized commands: \NAME([ARG]|{ARG})* for line in open(song_file, "r").readlines(): # Remove newline if line[-1] == '\n': line = line[:-1] - # Remove commends and \brk commands + # Remove comments and \brk commands text = re.sub(r"%.*$", "", line) text = re.sub(r"\\brk({})?", '', text) text = re.sub(r"``", u"\u201C", text) @@ -245,7 +280,8 @@ class SongLoader: continue current_verse.add_line(Line(text, extras)) - def sort_categories(self): + def sort_categories(self) -> dict[str, list[Song]]: + '''Returns a dictionary of categories to lists of songs (sorted by number).''' result = {} for c in self.categories: result[c] = sorted([s for s in self.songs if s.category == c], diff --git a/src/model.py b/src/model.py index 71f9298..a6e8b59 100644 --- a/src/model.py +++ b/src/model.py @@ -4,7 +4,8 @@ from datetime import datetime import locale -def join_list(the_list, separator="\n"): +def join_list(the_list: list, separator: str = "\n") -> str: + '''Join a list of objects in a string, with a separator.''' return ft.reduce(lambda x, y: x + (separator if x else "") + str(y), the_list, "")