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 import listdir
from os.path import isfile, join from os.path import isfile, join
from model import Audio
import re
from datetime import datetime from datetime import datetime
from model import Audio
def find_audios(index, audio_dir): def find_audios(index, audio_dir):

View file

@ -6,6 +6,7 @@ import pickle
def generate_songbook(songs, song_numbers, out_file, dj_engine): def generate_songbook(songs, song_numbers, out_file, dj_engine):
'''Generate an HTML file with a sequence of songs.'''
# Build the list of songs # Build the list of songs
song_list = [] song_list = []
for n in song_numbers: for n in song_numbers:
@ -24,6 +25,7 @@ def generate_songbook(songs, song_numbers, out_file, dj_engine):
def create_argparser(): def create_argparser():
'''Parse main's arguments.'''
parser = latex_scanner.create_argparser() 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("--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"], 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 from model import Chord, Line, Song, Verse
def mkdir(path): def mkdir(path: str) -> None:
if not os.path.exists(path): if not os.path.exists(path):
os.mkdir(path) os.mkdir(path)
@ -19,33 +19,40 @@ def mkdir(path):
# Note that re.match prepends ^ to the pattern, whereas re.search doesn't # 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: if text is None:
return None return None
match = re.search(key + "={(.*?)}", text) match = re.search(key + "={(.*?)}", text)
return match.group(1) if match else None 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} payload = {'type': the_type, 'data': data} if data else {'type': the_type}
if index not in extra: if index not in extra:
extra[index] = [] extra[index] = []
extra[index].append(payload) extra[index].append(payload)
class SongLoader: class SongLoader:
def __init__(self, latex_file, audio_dir=None): '''Parses LaTeX files to build a collection of song objects.'''
self.index = 1
self.category = None def __init__(self, latex_file: str, audio_dir: str | None = None):
self.categories = [] '''Initializes and populates a LaTeX reader.'''
self.songs = [] self.index: int = 1
self.category: str | None = None
self.categories: list[str] = []
self.songs: list[Song] = []
if audio_dir: if audio_dir:
self.audio_dir = audio_dir self.audio_dir = audio_dir
self.scan(latex_file) 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') main_file = open(latex_file, 'r')
canciones_dir = join(str(Path(latex_file).parent), "canciones")
for line in main_file.readlines(): for line in main_file.readlines():
# Remove newline # Remove newline
if line[-1] == '\n': if line[-1] == '\n':
@ -61,14 +68,18 @@ class SongLoader:
self.category = re_chapter_match.group(1) self.category = re_chapter_match.group(1)
self.categories.append(self.category) self.categories.append(self.category)
# Traverse into \input commands if path starts w/ 'canciones/' # 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: 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"): if not input_file.endswith(".tex"):
input_file += ".tex" input_file += ".tex"
self.scan_song_file(input_file) 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.index = start_index
self.category = "Nuevas" self.category = "Nuevas"
self.categories.append(self.category) self.categories.append(self.category)
@ -81,22 +92,46 @@ class SongLoader:
print("Scanning extra file", f) print("Scanning extra file", f)
self.scan_song_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 # Variables
ignore = False ignore: bool = False
current_song = None current_song: Song | None = None
current_verse = None current_verse: Verse | None = None
memory = None memory: str | None = None
memorizing = False memorizing: bool = False
replay_index = 0 replay_index: int = 0
transpose = 0 transpose: int = 0
trfmt = "normal" 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(): for line in open(song_file, "r").readlines():
# Remove newline # Remove newline
if line[-1] == '\n': if line[-1] == '\n':
line = line[:-1] line = line[:-1]
# Remove commends and \brk commands # Remove comments and \brk commands
text = re.sub(r"%.*$", "", line) text = re.sub(r"%.*$", "", line)
text = re.sub(r"\\brk({})?", '', text) text = re.sub(r"\\brk({})?", '', text)
text = re.sub(r"``", u"\u201C", text) text = re.sub(r"``", u"\u201C", text)
@ -245,7 +280,8 @@ class SongLoader:
continue continue
current_verse.add_line(Line(text, extras)) 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 = {} result = {}
for c in self.categories: for c in self.categories:
result[c] = sorted([s for s in self.songs if s.category == c], 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 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, "") return ft.reduce(lambda x, y: x + (separator if x else "") + str(y), the_list, "")