Implement move instruction generation

This commit is contained in:
Jakob Moser 2025-06-01 12:11:35 +02:00
parent 86a870d429
commit fb031fcaf6
Signed by: jakob
GPG Key ID: 3EF2BA2851B3F53C

View File

@ -1,13 +1,56 @@
import re
from collections.abc import Sequence from collections.abc import Sequence
from pathlib import Path from pathlib import Path
from karaokatalog.instructions.MoveInstruction import MoveInstruction from karaokatalog.instructions.MoveInstruction import MoveInstruction
from karaokatalog.Song import Song from karaokatalog.Song import Song
FORBIDDEN_CHARACTERS = re.compile(r'[/<>:"\\|?*]')
def _get_canonical_song_dir(song: Song, variant: int = 0) -> Path:
"""
Get the (relative) canonical directory in which this song should be located, that is
the directory f"{song.artist}/{song.title}".
Illegal characters are replaced. If variant > 0, f" ({variant})" is appended to the result.
"""
variant_suffix = f" ({variant})" if variant > 0 else ""
return Path(FORBIDDEN_CHARACTERS.sub("", song.artist)) / Path(
FORBIDDEN_CHARACTERS.sub("", song.title) + variant_suffix
)
def move(songs: Sequence[Song], base_dir: Path) -> Sequence[MoveInstruction]: def move(songs: Sequence[Song], base_dir: Path) -> Sequence[MoveInstruction]:
""" """
Create move instructions to move every song into the proper song directory Create move instructions to move every song into the proper song directory
within the given base_dir. within the given base_dir.
""" """
raise NotImplementedError() # TODO song_dirs = set(song.dir.relative_to(base_dir) for song in songs)
move_instructions = []
for song in songs:
absolute_song_dir = song.dir
song_dir = absolute_song_dir.relative_to(base_dir)
canonical_song_dir = _get_canonical_song_dir(song)
if song_dir not in song_dirs:
# A move instruction has already been generated for the dir this song is in
# (which is possible, because some dirs contain multiple (variants of) songs)
continue
if song_dir != canonical_song_dir:
# song_dir is not a good name, we want to replace it, so this path will soon be free
song_dirs.remove(song_dir)
# Find a canonical song dir variant that does not yet exist
variant = 1
while canonical_song_dir in song_dirs:
canonical_song_dir = _get_canonical_song_dir(song, variant)
song_dirs.add(canonical_song_dir)
move_instructions.append(
MoveInstruction(absolute_song_dir, base_dir / canonical_song_dir)
)
return tuple(move_instructions)