mypy strict support!
This commit is contained in:
parent
1804ddf457
commit
5d6ac79cd1
1 changed files with 14 additions and 30 deletions
44
bcao.py
44
bcao.py
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue