Verified Commit fb031fca authored by Jakob Moser's avatar Jakob Moser
Browse files

Implement move instruction generation

parent 86a870d4
Loading
Loading
Loading
Loading
+44 −1
Changes for karaokatalog/organize/move.py: 44 added lines, 1 removed line.
Original line number Diff line number Diff line
import re
from collections.abc import Sequence
from pathlib import Path

from karaokatalog.instructions.MoveInstruction import MoveInstruction
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]:
    """
    Create move instructions to move every song into the proper song directory
    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)