documentacion y pistas de tipo en metodos

This commit is contained in:
Carlos Galindo 2023-09-08 12:15:30 +02:00
parent 03522304fa
commit bc4e7ed51d
4 changed files with 67 additions and 28 deletions

View file

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

View file

@ -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"],

View file

@ -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],

View file

@ -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, "")