def test_validate_lastfm_artist_tags_fallback(self):
        validator = ReleaseValidator(get_lastfmcache(genres_release=OrderedDict()))

        release = create_test_release(genres=["genre 1"])

        violations = validator.validate(release)
        assert len(violations) == 1
    def test_validate_lastfm_release_tags(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release(genres=["genre 1"])

        violations = validator.validate(release)
        assert len(violations) == 1
    def test_fix(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release(release_title="mezzanine", date="")
        fixed = validator.fix(release)
        assert fixed != release

        mockito.unstub()
    def test_validate_release_title_whitespace(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release(release_title=" Mezzanine")

        violations = validator.validate(release)
        assert len(violations) == len(release.tracks)

        mockito.unstub()
    def test_validate_release_artist_whitespace(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release(release_artists=[" Massive Attack"])

        violations = validator.validate(release)
        assert len(violations) == len(release.tracks) + 1

        mockito.unstub()
    def test_lastfm_fix_track_title_lowercase(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release()
        next(iter(release.tracks.values())).track_title = "angel"
        fixed = validator.fix(release)
        assert fixed != release

        mockito.unstub()
    def test_validate_release_date(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release(date="")

        violations = validator.validate(release)
        assert len(violations) == 2

        mockito.unstub()
    def test_validate_lastfm_release_title(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release(release_title="mezzanine")

        violations = validator.validate(release)
        assert len(violations) == 1

        mockito.unstub()
    def test_validate_genre_whitespace(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release(genres=[" Bass"])

        violations = validator.validate(release)
        assert len(violations) == len(release.tracks) + 1

        mockito.unstub()
    def test_validate_artist_whitespace(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release()
        next(iter(release.tracks.values())).artists[0] = " Massive Attack"

        violations = validator.validate(release)
        assert len(violations) == 2

        mockito.unstub()
    def test_validate_tag_types(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release()
        next(iter(release.tracks.values())).stream_info.tag_type = TagType.FLAC

        violations = validator.validate(release)
        assert len(violations) > 0

        mockito.unstub()
    def test_validate_invalid_disc_numbers(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release()
        next(iter(release.tracks.values())).disc_number = 3

        violations = validator.validate(release)
        assert len(violations) > 0

        mockito.unstub()
    def test_validate_missing_total_tracks(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release()
        next(iter(release.tracks.values())).total_tracks = None

        violations = validator.validate(release)
        assert len(violations) == 1

        mockito.unstub()
    def test_validate_release_artists(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release()
        next(iter(release.tracks.values())).release_artists = []

        violations = validator.validate(release)
        assert len(violations) == 1

        mockito.unstub()
    def test_validate_track_title_whitespace(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release()
        next(iter(release.tracks.values())).track_title = " A Bad Track Title"

        violations = validator.validate(release)
        assert len(violations) == 2

        mockito.unstub()
    def test_validate_cbr_bitrates(self):
        validator = ReleaseValidator(get_lastfmcache())

        release = create_test_release()
        next(iter(release.tracks.values())).stream_info.bitrate = 160000

        violations = validator.validate(release)
        assert len(violations) == 1

        mockito.unstub()
Example #17
0
def validate_releases(validator: ReleaseValidator, release_dirs: List[str],
                      args: argparse.Namespace) -> None:
    """Validate releases found in the scan directory"""

    # assemble_discs(release_dirs, False)

    for curr_dir in release_dirs:
        audio, non_audio, unreadable = load_directory(curr_dir)
        release = Release(audio, guess_category_from_path(curr_dir),
                          guess_source_from_path(curr_dir))

        codec_short = not args.full_codec_names
        violations = validator.validate(release)
        validate_folder_name(release, violations,
                             os.path.split(curr_dir)[1], False, codec_short)
        add_unreadable_files(violations, unreadable)

        print("{0} violations: {1}".format(format_violations_str(violations),
                                           curr_dir))

        if args.show_violations:
            print_list(violations)
Example #18
0
def main():
    args = parse_args()

    src_folder = os.path.abspath(args.path)
    if not os.path.isdir(src_folder):
        raise ValueError("Invalid source folder: {0}".format(src_folder))

    dest_folder = None
    if args.move_fixed:
        dest_folder = os.path.abspath(src_folder)
    elif args.move_fixed_to:
        dest_folder = os.path.abspath(args.move_fixed_to)
        if not os.path.isdir(dest_folder):
            raise ValueError(
                "Invalid destination folder: {0}".format(dest_folder))

    invalid_folder = None
    if args.move_invalid:
        if args.move_invalid not in [v.value for v in ViolationType]:
            raise ValueError(
                "Invalid violation type '{0}', must be one of {1}".format(
                    args.move_invalid,
                    ", ".join([v.value for v in ViolationType])))
        if not args.move_invalid_to:
            raise ValueError(
                "--move-invalid must be accompanied by --move-invalid-to")
        invalid_folder = os.path.abspath(args.move_invalid_to)
        if not os.path.isdir(invalid_folder):
            raise ValueError(
                "Destination folder for invalid releases does not exist")

    duplicate_folder = None
    if args.move_duplicate_to:
        duplicate_folder = os.path.abspath(args.move_duplicate_to)
        if not os.path.isdir(duplicate_folder):
            raise ValueError(
                "Invalid duplicates folder: {0}".format(duplicate_folder))

    # guess group_by_category, if it was not set, using the contents of the destination folder
    if not args.group_by_category:
        args.group_by_category = guess_group_by_category(
            src_folder, dest_folder)

    if args.mode == "releases":
        list_releases(get_release_dirs(src_folder))

    elif args.mode in ["validate", "fix"]:
        lastfm = LastfmCache(lastfmcache_api_url=get_lastfmcache_api_url())
        lastfm.enable_file_cache(86400 * 365 * 5)

        validator = ReleaseValidator(lastfm)
        validator.disable_lastfm_track_title_validation()

        if args.expunge_comments_with_substring:
            validator.add_forbidden_comment_substring(
                args.expunge_comments_with_substring)

        if args.mode == "validate":
            validate_releases(validator, get_release_dirs(src_folder), args)

        elif args.mode == "fix":
            assemble_discs(get_release_dirs(src_folder), True)
            fix_releases(validator, get_release_dirs(src_folder), args,
                         dest_folder, invalid_folder, duplicate_folder)
Example #19
0
def fix_releases(validator: ReleaseValidator, release_dirs: Iterator[str],
                 args: argparse.Namespace, dest_folder: str,
                 invalid_folder: str, duplicate_folder: str) -> None:
    """Fix releases found in the scan directory"""

    unique_releases = set()

    for curr_dir in release_dirs:
        if not can_lock_path(curr_dir):
            logging.getLogger(__name__).error(
                "Could not lock directory {0}".format(curr_dir))
            continue

        audio, non_audio, unreadable = load_directory(curr_dir)

        release = Release(audio, guess_category_from_path(curr_dir),
                          guess_source_from_path(curr_dir))

        fixed = validator.fix(release, os.path.split(curr_dir)[1])

        if not args.dry_run:
            for x in fixed.tracks:
                if fixed.tracks[x] != release.tracks[x] or fixed.tracks[
                        x].always_write:
                    cleartag.write_tags(os.path.join(curr_dir, x),
                                        fixed.tracks[x])

        # rename files
        rename_files(fixed, curr_dir, args.dry_run)

        new_tracks = OrderedDict()
        for x in fixed.tracks:
            correct_filename = fixed.tracks[x].get_filename(fixed.is_va())
            if correct_filename:
                new_tracks[correct_filename] = fixed.tracks[x]
            else:
                new_tracks[x] = fixed.tracks[x]
        fixed.tracks = new_tracks

        # calculate violations before and after fixing
        codec_short = not args.full_codec_names
        old_violations = validator.validate(release)
        validate_folder_name(release, old_violations,
                             os.path.split(curr_dir)[1], False,
                             args.group_by_category, codec_short)
        add_unreadable_files(old_violations, unreadable)

        violations = validator.validate(fixed)
        validate_folder_name(fixed, violations,
                             os.path.split(curr_dir)[1], True,
                             args.group_by_category, codec_short)
        add_unreadable_files(violations, unreadable)

        if len(violations) == 0:
            moved_dir = move_rename_folder(fixed, unique_releases, curr_dir,
                                           dest_folder, duplicate_folder, args)
        else:
            moved_dir = move_invalid_folder(curr_dir, invalid_folder,
                                            violations, args.move_invalid)

        enforce_max_path(moved_dir)

        print("{0} violations: {1}".format(
            format_violations_str(old_violations, violations), moved_dir))

        if args.show_violations:
            if old_violations:
                print("Before")
                print_list(old_violations)

            if violations:
                print("After:")
                print_list(violations)