mypy strict support!

This commit is contained in:
Lynne Megido 2020-10-26 23:05:18 +10:00
parent 1804ddf457
commit 5d6ac79cd1
Signed by: lynnesbian
GPG key ID: F0A184B5213D9F90

44
bcao.py
View file

@ -16,7 +16,7 @@ from os import path
from base64 import b64encode from base64 import b64encode
from zipfile import ZipFile from zipfile import ZipFile
from pathlib import Path from pathlib import Path
from typing import Optional, Union, List, Dict from typing import Optional, Union, List, Dict, Any
# pycharm tells me some of these classes shouldn't be imported because they're not declared in __all__. # pycharm tells me some of these classes shouldn't be imported because they're not declared in __all__.
# however, the mutagen docs show example code where someone creates a mutagen.flac.Picture by referring to it as # however, the mutagen docs show example code where someone creates a mutagen.flac.Picture by referring to it as
@ -37,6 +37,7 @@ fully_supported: List[str] = ["ogg", "flac", "mp3", "m4a", "wav"]
MutagenFile = Union[MP3, FLAC, OggVorbis, mutagen.FileType] MutagenFile = Union[MP3, FLAC, OggVorbis, mutagen.FileType]
MutagenTags = Union[mutagen.id3.ID3Tags, mutagen.mp4.Tags, mutagen.oggvorbis.OggVCommentDict] MutagenTags = Union[mutagen.id3.ID3Tags, mutagen.mp4.Tags, mutagen.oggvorbis.OggVCommentDict]
args: argparse.Namespace args: argparse.Namespace
tmp_dir: tempfile.TemporaryDirectory[Any]
class SongInfo: class SongInfo:
tag_lookup: Dict[str, Dict[str, str]] = { tag_lookup: Dict[str, Dict[str, str]] = {
@ -46,6 +47,7 @@ class SongInfo:
"album": {"id3": "TALB", "m4a": "©alb", "vorbis": "album"}, "album": {"id3": "TALB", "m4a": "©alb", "vorbis": "album"},
"album_artist": {"id3": "TPE2", "m4a": "aART", "vorbis": "albumartist"} "album_artist": {"id3": "TPE2", "m4a": "aART", "vorbis": "albumartist"}
} }
format_lookup: Dict[str, str] = { format_lookup: Dict[str, str] = {
"mp3": "id3", "mp3": "id3",
"m4a": "m4a", "m4a": "m4a",
@ -110,10 +112,10 @@ class SongInfo:
self.tags[standard_name] = value_list[0] self.tags[standard_name] = value_list[0]
self.list_tags[standard_name] = value_list self.list_tags[standard_name] = value_list
def get_target_name(self, zeroes: int): def get_target_name(self, zeroes: int) -> str:
return f"{self.tags['track'].zfill(zeroes)} {self.tags['title']}.{self.format}" return f"{self.tags['track'].zfill(zeroes)} {self.tags['title']}.{self.format}"
def has_cover(self): def has_cover(self) -> bool:
if self.format == "ogg": if self.format == "ogg":
return "metadata_block_picture" in self.m_tags and len(self.m_tags["metadata_block_picture"]) != 0 return "metadata_block_picture" in self.m_tags and len(self.m_tags["metadata_block_picture"]) != 0
@ -132,7 +134,7 @@ class SongInfo:
raise NotImplementedError("Song format not yet implemented.") raise NotImplementedError("Song format not yet implemented.")
def set_cover(self, to_embed: Union[Picture, APIC, MP4Cover]): def set_cover(self, to_embed: Union[Picture, APIC, MP4Cover]) -> None:
# embed cover art # embed cover art
if self.format == "ogg": if self.format == "ogg":
self.m_tags["metadata_block_picture"] = [b64encode(to_embed.write()).decode("ascii")] self.m_tags["metadata_block_picture"] = [b64encode(to_embed.write()).decode("ascii")]
@ -146,43 +148,26 @@ class SongInfo:
self.m_file.save() self.m_file.save()
def __getitem__(self, item): def __getitem__(self, item: str) -> str:
return self.tags[item] return self.tags[item]
def log(message: str, importance: int = 0): def log(message: str, importance: int = 0) -> None:
if not args.quiet or importance > 0: if not args.quiet or importance > 0:
print(message) print(message)
def die(message: str, code: int = 1): def die(message: str, code: int = 1) -> None:
print(message) print(message)
sys.exit(code) sys.exit(code)
def has_cover(mut_song: MutagenFile):
if isinstance(mut_song, OggVorbis):
return "metadata_block_picture" in mut_song and len(mut_song["metadata_block_picture"]) != 0
if isinstance(mut_song, FLAC):
return len(mut_song.pictures) != 0
if isinstance(mut_song, MP3):
apics: List[APIC] = mut_song.tags.getall("APIC")
for apic in apics:
if apic.type == PictureType.COVER_FRONT:
return True
return False
if isinstance(mut_song, MP4):
return 'covr' in mut_song and len(mut_song['covr']) != 0
raise NotImplementedError("Song format not yet implemented.")
def sanitise(in_str: str) -> str: def sanitise(in_str: str) -> str:
if args.sanitise: if args.sanitise:
return re.sub(r"[?\\/:|*\"<>]", "_", in_str) return re.sub(r"[?\\/:|*\"<>]", "_", in_str)
return in_str return in_str
def main(): def main() -> None:
global args, tmp_dir
# noinspection PyTypeChecker # noinspection PyTypeChecker
parser = argparse.ArgumentParser(usage='%(prog)s zip [options]', parser = argparse.ArgumentParser(usage='%(prog)s zip [options]',
formatter_class=argparse.RawTextHelpFormatter, formatter_class=argparse.RawTextHelpFormatter,
@ -203,7 +188,6 @@ def main():
parser.add_argument('-t', '--threshold', dest='threshold', nargs=1, default=300, parser.add_argument('-t', '--threshold', dest='threshold', nargs=1, default=300,
help="Maximum acceptable file size for cover art, in kilobytes.\nDefault: %(default)s") help="Maximum acceptable file size for cover art, in kilobytes.\nDefault: %(default)s")
global args
args = parser.parse_args() args = parser.parse_args()
# convert args.threshold to bytes # convert args.threshold to bytes
args.threshold *= 1024 args.threshold *= 1024
@ -212,7 +196,7 @@ def main():
die(f"Couldn't find {args.zip}.", 2) die(f"Couldn't find {args.zip}.", 2)
log("Extracting...") log("Extracting...")
tmp_dir: tempfile.TemporaryDirectory = tempfile.TemporaryDirectory() tmp_dir = tempfile.TemporaryDirectory()
tmp: str = tmp_dir.name tmp: str = tmp_dir.name
cover: Optional[str] = None cover: Optional[str] = None
song_names: List[str] = [] song_names: List[str] = []
@ -327,7 +311,7 @@ def main():
) )
artists: List[str] = [] artists: List[str] = []
album: Optional[str] = None album: str = "Unknown album" # it SHOULD be impossible for this value to ever appear
songs: Dict[str, str] = {} songs: Dict[str, str] = {}
zeroes = min(len(song_names), 2) zeroes = min(len(song_names), 2)
first_loop: bool = True first_loop: bool = True