mirror of
https://github.com/fergalmoran/picard.git
synced 2025-12-26 19:29:01 +00:00
If a file is moved to a track where the metadata matches perfectly but only cover art is different, then the similarity score of this file was not recalculated. That means the file retains the similarity of the previous (probably bad) match. Also only do this change if the state was NORMAL before (similar to the other state updates, ignoring states like PENDING and ERROR).
614 lines
22 KiB
Python
614 lines
22 KiB
Python
# -*- coding: utf-8 -*-
|
|
#
|
|
# Picard, the next-generation MusicBrainz tagger
|
|
#
|
|
# Copyright (C) 2018-2022 Philipp Wolfer
|
|
# Copyright (C) 2019-2022 Laurent Monin
|
|
# Copyright (C) 2021 Bob Swift
|
|
# Copyright (C) 2021 Sophist-UK
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License
|
|
# as published by the Free Software Foundation; either version 2
|
|
# of the License, or (at your option) any later version.
|
|
#
|
|
# This program is distributed in the hope that it will be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write to the Free Software
|
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
|
|
import os
|
|
import re
|
|
from types import GeneratorType
|
|
import unittest
|
|
from unittest.mock import MagicMock
|
|
|
|
from test.picardtestcase import PicardTestCase
|
|
from test.test_coverart_image import create_image
|
|
|
|
from picard import config
|
|
from picard.const.sys import (
|
|
IS_MACOS,
|
|
IS_WIN,
|
|
)
|
|
from picard.file import File
|
|
from picard.metadata import Metadata
|
|
|
|
|
|
class DataObjectTest(PicardTestCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.tagger.acoustidmanager = MagicMock()
|
|
self.file = File('somepath/somefile.mp3')
|
|
self.set_config_values({
|
|
'save_acoustid_fingerprints': True,
|
|
})
|
|
|
|
def test_filename(self):
|
|
self.assertEqual('somepath/somefile.mp3', self.file.filename)
|
|
self.assertEqual('somefile.mp3', self.file.base_filename)
|
|
|
|
def test_tracknumber(self):
|
|
self.assertEqual(0, self.file.tracknumber)
|
|
self.file.metadata['tracknumber'] = '42'
|
|
self.assertEqual(42, self.file.tracknumber)
|
|
self.file.metadata['tracknumber'] = 'FOURTYTWO'
|
|
self.assertEqual(0, self.file.tracknumber)
|
|
|
|
def test_discnumber(self):
|
|
self.assertEqual(0, self.file.discnumber)
|
|
self.file.metadata['discnumber'] = '42'
|
|
self.assertEqual(42, self.file.discnumber)
|
|
self.file.metadata['discnumber'] = 'FOURTYTWO'
|
|
self.assertEqual(0, self.file.discnumber)
|
|
|
|
def test_set_acoustid_fingerprint(self):
|
|
fingerprint = 'foo'
|
|
length = 36
|
|
self.file.set_acoustid_fingerprint(fingerprint, length)
|
|
self.assertEqual(fingerprint, self.file.acoustid_fingerprint)
|
|
self.assertEqual(length, self.file.acoustid_length)
|
|
self.tagger.acoustidmanager.add.assert_called_with(self.file, None)
|
|
self.tagger.acoustidmanager.add.reset_mock()
|
|
self.file.set_acoustid_fingerprint(fingerprint, length)
|
|
self.tagger.acoustidmanager.add.assert_not_called()
|
|
self.tagger.acoustidmanager.remove.assert_not_called()
|
|
self.assertEqual(fingerprint, self.file.metadata['acoustid_fingerprint'])
|
|
|
|
def test_set_acoustid_fingerprint_no_length(self):
|
|
self.file.metadata.length = 42000
|
|
fingerprint = 'foo'
|
|
self.file.set_acoustid_fingerprint(fingerprint)
|
|
self.assertEqual(fingerprint, self.file.acoustid_fingerprint)
|
|
self.assertEqual(42, self.file.acoustid_length)
|
|
self.assertEqual(fingerprint, self.file.metadata['acoustid_fingerprint'])
|
|
|
|
def test_set_acoustid_fingerprint_unset(self):
|
|
self.file.acoustid_fingerprint = 'foo'
|
|
self.file.set_acoustid_fingerprint(None, 42)
|
|
self.tagger.acoustidmanager.add.assert_not_called()
|
|
self.tagger.acoustidmanager.remove.assert_called_with(self.file)
|
|
self.assertEqual(None, self.file.acoustid_fingerprint)
|
|
self.assertEqual(0, self.file.acoustid_length)
|
|
self.assertEqual('', self.file.metadata['acoustid_fingerprint'])
|
|
|
|
def format_specific_metadata(self):
|
|
values = ['foo', 'bar']
|
|
self.file.metadata['test'] = values
|
|
self.assertEqual(values, self.file.format_specific_metadata(self.file.metadata, 'test'))
|
|
|
|
def test_set_acoustid_fingerprint_no_save(self):
|
|
self.set_config_values({
|
|
'save_acoustid_fingerprints': False,
|
|
})
|
|
fingerprint = 'foo'
|
|
length = 36
|
|
self.file.set_acoustid_fingerprint(fingerprint, length)
|
|
self.assertEqual(fingerprint, self.file.acoustid_fingerprint)
|
|
self.assertEqual(length, self.file.acoustid_length)
|
|
self.assertEqual('', self.file.metadata['acoustid_fingerprint'])
|
|
|
|
|
|
class TestPreserveTimes(PicardTestCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.tmp_directory = self.mktmpdir()
|
|
filepath = os.path.join(self.tmp_directory, 'a.mp3')
|
|
self.file = File(filepath)
|
|
|
|
def _create_testfile(self):
|
|
# create a dummy file
|
|
with open(self.file.filename, 'w') as f:
|
|
f.write('xxx')
|
|
f.flush()
|
|
os.fsync(f.fileno())
|
|
|
|
def _modify_testfile(self):
|
|
# dummy file modification, append data to it
|
|
with open(self.file.filename, 'a') as f:
|
|
f.write('yyy')
|
|
f.flush()
|
|
os.fsync(f.fileno())
|
|
|
|
def _read_testfile(self):
|
|
with open(self.file.filename, 'r') as f:
|
|
return f.read()
|
|
|
|
def test_preserve_times(self):
|
|
self._create_testfile()
|
|
|
|
# test if times are preserved
|
|
(before_atime_ns, before_mtime_ns) = self.file._preserve_times(self.file.filename, self._modify_testfile)
|
|
|
|
# HERE an external access to the file is possible, modifying its access time
|
|
|
|
# read times again and compare with original
|
|
st = os.stat(self.file.filename)
|
|
(after_atime_ns, after_mtime_ns) = (st.st_atime_ns, st.st_mtime_ns)
|
|
|
|
# on macOS 10.14 and later os.utime only sets the times with second
|
|
# precision see https://tickets.metabrainz.org/browse/PICARD-1516.
|
|
# This also seems to depend on the Python build being used.
|
|
if IS_MACOS:
|
|
before_atime_ns //= 1000
|
|
before_mtime_ns //= 1000
|
|
after_atime_ns //= 1000
|
|
after_mtime_ns //= 1000
|
|
|
|
# modification times should be equal
|
|
self.assertEqual(before_mtime_ns, after_mtime_ns)
|
|
|
|
# access times may not be equal
|
|
# time difference should be positive and reasonably low (if no access in between, it should be 0)
|
|
delta = after_atime_ns - before_atime_ns
|
|
tolerance = 10**7 # 0.01 seconds
|
|
self.assertTrue(0 <= delta < tolerance, "0 <= %s < %s" % (delta, tolerance))
|
|
|
|
# ensure written data can be read back
|
|
# keep it at the end, we don't want to access file before time checks
|
|
self.assertEqual(self._read_testfile(), 'xxxyyy')
|
|
|
|
def test_preserve_times_nofile(self):
|
|
|
|
with self.assertRaises(self.file.PreserveTimesStatError):
|
|
self.file._preserve_times(self.file.filename,
|
|
self._modify_testfile)
|
|
with self.assertRaises(FileNotFoundError):
|
|
self._read_testfile()
|
|
|
|
def test_preserve_times_nofile_utime(self):
|
|
self._create_testfile()
|
|
|
|
def save():
|
|
os.remove(self.file.filename)
|
|
|
|
with self.assertRaises(self.file.PreserveTimesUtimeError):
|
|
self.file._preserve_times(self.file.filename, save)
|
|
|
|
|
|
class FakeMp3File(File):
|
|
EXTENSIONS = ['.mp3']
|
|
|
|
|
|
class FileNamingTest(PicardTestCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.file = File('/somepath/somefile.mp3')
|
|
self.set_config_values({
|
|
'ascii_filenames': False,
|
|
'clear_existing_tags': False,
|
|
'enabled_plugins': [],
|
|
'move_files_to': '/media/music',
|
|
'move_files': False,
|
|
'rename_files': False,
|
|
'windows_compatibility': True,
|
|
'windows_long_paths': False,
|
|
'file_renaming_scripts': {'test_id': {'script': '%album%/%title%'}},
|
|
'selected_file_naming_script_id': 'test_id',
|
|
})
|
|
self.metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
})
|
|
|
|
def test_make_filename_no_move_and_rename(self):
|
|
filename = self.file.make_filename(self.file.filename, self.metadata)
|
|
self.assertEqual(os.path.realpath(self.file.filename), filename)
|
|
|
|
def test_make_filename_rename_only(self):
|
|
config.setting['rename_files'] = True
|
|
filename = self.file.make_filename(self.file.filename, self.metadata)
|
|
self.assertEqual(os.path.realpath('/somepath/sometitle.mp3'), filename)
|
|
|
|
def test_make_filename_move_only(self):
|
|
config.setting['move_files'] = True
|
|
filename = self.file.make_filename(self.file.filename, self.metadata)
|
|
self.assertEqual(
|
|
os.path.realpath('/media/music/somealbum/somefile.mp3'),
|
|
filename)
|
|
|
|
def test_make_filename_move_and_rename(self):
|
|
config.setting['rename_files'] = True
|
|
config.setting['move_files'] = True
|
|
filename = self.file.make_filename(self.file.filename, self.metadata)
|
|
self.assertEqual(
|
|
os.path.realpath('/media/music/somealbum/sometitle.mp3'),
|
|
filename)
|
|
|
|
def test_make_filename_move_relative_path(self):
|
|
config.setting['move_files'] = True
|
|
config.setting['move_files_to'] = 'subdir'
|
|
filename = self.file.make_filename(self.file.filename, self.metadata)
|
|
self.assertEqual(
|
|
os.path.realpath('/somepath/subdir/somealbum/somefile.mp3'),
|
|
filename)
|
|
|
|
def test_make_filename_empty_script(self):
|
|
config.setting['rename_files'] = True
|
|
config.setting['file_renaming_scripts'] = {'test_id': {'script': '$noop()'}}
|
|
filename = self.file.make_filename(self.file.filename, self.metadata)
|
|
self.assertEqual(os.path.realpath('/somepath/somefile.mp3'), filename)
|
|
|
|
def test_make_filename_no_extension(self):
|
|
config.setting['rename_files'] = True
|
|
file_ = FakeMp3File('/somepath/_')
|
|
filename = file_.make_filename(file_.filename, self.metadata)
|
|
self.assertEqual(os.path.realpath('/somepath/sometitle.mp3'), filename)
|
|
|
|
def test_make_filename_lowercase_extension(self):
|
|
config.setting['rename_files'] = True
|
|
file_ = FakeMp3File('/somepath/somefile.MP3')
|
|
filename = file_.make_filename(file_.filename, self.metadata)
|
|
self.assertEqual(os.path.realpath('/somepath/sometitle.mp3'), filename)
|
|
|
|
def test_make_filename_scripted_extension(self):
|
|
config.setting['rename_files'] = True
|
|
config.setting['file_renaming_scripts'] = {'test_id': {'script': '$set(_extension,.foo)%title%'}}
|
|
filename = self.file.make_filename(self.file.filename, self.metadata)
|
|
self.assertEqual(os.path.realpath('/somepath/sometitle.foo'), filename)
|
|
|
|
def test_make_filename_replace_trailing_dots(self):
|
|
config.setting['rename_files'] = True
|
|
config.setting['move_files'] = True
|
|
config.setting['windows_compatibility'] = True
|
|
metadata = Metadata({
|
|
'album': 'somealbum.',
|
|
'title': 'sometitle',
|
|
})
|
|
filename = self.file.make_filename(self.file.filename, metadata)
|
|
self.assertEqual(
|
|
os.path.realpath('/media/music/somealbum_/sometitle.mp3'),
|
|
filename)
|
|
|
|
@unittest.skipUnless(not IS_WIN, "non-windows test")
|
|
def test_make_filename_keep_trailing_dots(self):
|
|
config.setting['rename_files'] = True
|
|
config.setting['move_files'] = True
|
|
config.setting['windows_compatibility'] = False
|
|
metadata = Metadata({
|
|
'album': 'somealbum.',
|
|
'title': 'sometitle',
|
|
})
|
|
filename = self.file.make_filename(self.file.filename, metadata)
|
|
self.assertEqual(
|
|
os.path.realpath('/media/music/somealbum./sometitle.mp3'),
|
|
filename)
|
|
|
|
def test_make_filename_replace_leading_dots(self):
|
|
config.setting['rename_files'] = True
|
|
config.setting['move_files'] = True
|
|
config.setting['windows_compatibility'] = True
|
|
metadata = Metadata({
|
|
'album': '.somealbum',
|
|
'title': '.sometitle',
|
|
})
|
|
filename = self.file.make_filename(self.file.filename, metadata)
|
|
self.assertEqual(
|
|
os.path.realpath('/media/music/_somealbum/_sometitle.mp3'),
|
|
filename)
|
|
|
|
|
|
class FileGuessTracknumberAndTitleTest(PicardTestCase):
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.set_config_values({
|
|
'guess_tracknumber_and_title': True,
|
|
})
|
|
|
|
def test_no_guess(self):
|
|
f = File('/somepath/01 somefile.mp3')
|
|
metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
'tracknumber': '2',
|
|
})
|
|
f._guess_tracknumber_and_title(metadata)
|
|
self.assertEqual(metadata['tracknumber'], '2')
|
|
self.assertEqual(metadata['title'], 'sometitle')
|
|
|
|
def test_guess_title(self):
|
|
f = File('/somepath/01 somefile.mp3')
|
|
metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'tracknumber': '2',
|
|
})
|
|
f._guess_tracknumber_and_title(metadata)
|
|
self.assertEqual(metadata['tracknumber'], '2')
|
|
self.assertEqual(metadata['title'], 'somefile')
|
|
|
|
def test_guess_tracknumber(self):
|
|
f = File('/somepath/01 somefile.mp3')
|
|
metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
})
|
|
f._guess_tracknumber_and_title(metadata)
|
|
self.assertEqual(metadata['tracknumber'], '1')
|
|
|
|
def test_guess_title_tracknumber(self):
|
|
f = File('/somepath/01 somefile.mp3')
|
|
metadata = Metadata({
|
|
'album': 'somealbum',
|
|
})
|
|
f._guess_tracknumber_and_title(metadata)
|
|
self.assertEqual(metadata['tracknumber'], '1')
|
|
self.assertEqual(metadata['title'], 'somefile')
|
|
|
|
|
|
class FileAdditionalFilesPatternsTest(PicardTestCase):
|
|
|
|
def test_empty_patterns(self):
|
|
self.assertEqual(File._compile_move_additional_files_pattern(' '), set())
|
|
|
|
def test_simple_patterns(self):
|
|
pattern = 'cover.jpg'
|
|
expected = {
|
|
(re.compile('(?s:cover\\.jpg)\\Z', re.IGNORECASE), False)
|
|
}
|
|
self.assertEqual(File._compile_move_additional_files_pattern(pattern), expected)
|
|
|
|
def test_whitespaces_patterns(self):
|
|
pattern = " a \n b "
|
|
expected = {
|
|
(re.compile('(?s:a)\\Z', re.IGNORECASE), False),
|
|
(re.compile('(?s:b)\\Z', re.IGNORECASE), False),
|
|
}
|
|
self.assertEqual(File._compile_move_additional_files_pattern(pattern), expected)
|
|
|
|
def test_duplicated_patterns(self):
|
|
pattern = 'cover.jpg cover.jpg COVER.JPG'
|
|
expected = {
|
|
(re.compile('(?s:cover\\.jpg)\\Z', re.IGNORECASE), False)
|
|
}
|
|
self.assertEqual(File._compile_move_additional_files_pattern(pattern), expected)
|
|
|
|
def test_simple_hidden_patterns(self):
|
|
pattern = 'cover.jpg .hidden'
|
|
expected = {
|
|
(re.compile('(?s:cover\\.jpg)\\Z', re.IGNORECASE), False),
|
|
(re.compile('(?s:\\.hidden)\\Z', re.IGNORECASE), True)
|
|
}
|
|
self.assertEqual(File._compile_move_additional_files_pattern(pattern), expected)
|
|
|
|
def test_wildcard_patterns(self):
|
|
pattern = 'c?ver.jpg .h?dden* *.jpg *.JPG'
|
|
expected = {
|
|
(re.compile('(?s:c.ver\\.jpg)\\Z', re.IGNORECASE), False),
|
|
(re.compile('(?s:\\.h.dden.*)\\Z', re.IGNORECASE), True),
|
|
(re.compile('(?s:.*\\.jpg)\\Z', re.IGNORECASE), False),
|
|
}
|
|
self.assertEqual(File._compile_move_additional_files_pattern(pattern), expected)
|
|
|
|
|
|
class FileUpdateTest(PicardTestCase):
|
|
|
|
def setUp(self):
|
|
super().setUp()
|
|
self.file = File('/somepath/somefile.mp3')
|
|
self.INVALIDSIMVAL = 666
|
|
self.file.similarity = self.INVALIDSIMVAL # to check if changed or not
|
|
self.file.supports_tag = lambda x: False if x.startswith('unsupported') else True
|
|
self.set_config_values({
|
|
'clear_existing_tags': False,
|
|
'compare_ignore_tags': [],
|
|
'enabled_plugins': [],
|
|
})
|
|
|
|
def test_same_image(self):
|
|
image = create_image(b'a')
|
|
self.file.metadata.images = [image]
|
|
self.file.orig_metadata.images = [image]
|
|
self.file.state = File.NORMAL
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0) # it should be modified
|
|
self.assertEqual(self.file.state, File.NORMAL)
|
|
|
|
def test_same_image_pending(self):
|
|
image = create_image(b'a')
|
|
self.file.metadata.images = [image]
|
|
self.file.orig_metadata.images = [image]
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.PENDING)
|
|
|
|
def test_same_image_changed_state(self):
|
|
image = create_image(b'a')
|
|
self.file.metadata.images = [image]
|
|
self.file.orig_metadata.images = [image]
|
|
self.file.state = File.CHANGED
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.NORMAL)
|
|
|
|
def test_changed_image(self):
|
|
old_image = create_image(b'a')
|
|
new_image = create_image(b'b')
|
|
self.file.metadata.images = [new_image]
|
|
self.file.orig_metadata.images = [old_image]
|
|
self.file.state = File.NORMAL
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.CHANGED)
|
|
|
|
def test_signal(self):
|
|
# just for coverage
|
|
self.file.update(signal=True)
|
|
self.assertEqual(self.file.metadata, Metadata())
|
|
self.assertEqual(self.file.orig_metadata, Metadata())
|
|
|
|
def test_tags_to_update(self):
|
|
self.file.orig_metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
'ignoreme_old': 'a',
|
|
'~ignoreme_old': 'b',
|
|
'unsupported_old': 'c',
|
|
})
|
|
self.file.metadata = Metadata({
|
|
'artist': 'someartist',
|
|
'ignoreme_new': 'd',
|
|
'~ignoreme_new': 'e',
|
|
'unsupported_new': 'f',
|
|
})
|
|
|
|
ignore_tags = {'ignoreme_old', 'ignoreme_new'}
|
|
|
|
expected = {'album', 'title', 'artist'}
|
|
result = self.file._tags_to_update(ignore_tags)
|
|
self.assertIsInstance(result, GeneratorType)
|
|
self.assertEqual(set(result), expected)
|
|
|
|
def test_unchanged_metadata(self):
|
|
self.file.orig_metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
})
|
|
self.file.metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
})
|
|
self.file.state = File.NORMAL
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.NORMAL)
|
|
|
|
def test_changed_metadata(self):
|
|
self.file.orig_metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
})
|
|
self.file.metadata = Metadata({
|
|
'album': 'somealbum2',
|
|
'title': 'sometitle2',
|
|
})
|
|
self.file.state = File.NORMAL
|
|
|
|
self.file.update(signal=False)
|
|
self.assertLess(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.CHANGED)
|
|
|
|
def test_changed_metadata_pending(self):
|
|
self.file.orig_metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
})
|
|
self.file.metadata = Metadata({
|
|
'album': 'somealbum2',
|
|
'title': 'sometitle2',
|
|
})
|
|
|
|
self.file.update(signal=False)
|
|
self.assertLess(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.PENDING) # it shouldn't be modified
|
|
|
|
def test_clear_existing(self):
|
|
self.file.orig_metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
})
|
|
self.file.metadata = Metadata()
|
|
self.file.state = File.NORMAL
|
|
|
|
config.setting["clear_existing_tags"] = True
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 0.0)
|
|
self.assertEqual(self.file.state, File.CHANGED)
|
|
|
|
def test_no_new_metadata(self):
|
|
self.file.orig_metadata = Metadata({
|
|
'album': 'somealbum',
|
|
'title': 'sometitle',
|
|
})
|
|
self.file.metadata = Metadata()
|
|
self.file.state = File.NORMAL
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.NORMAL)
|
|
|
|
def test_tilde_tag(self):
|
|
self.file.orig_metadata = Metadata()
|
|
self.file.metadata = Metadata({
|
|
'~tag': 'value'
|
|
})
|
|
self.file.state = File.NORMAL
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.NORMAL)
|
|
|
|
def test_ignored_tag(self):
|
|
self.file.orig_metadata = Metadata()
|
|
self.file.metadata = Metadata({
|
|
'tag': 'value'
|
|
})
|
|
self.file.state = File.NORMAL
|
|
|
|
config.setting["compare_ignore_tags"] = ['tag']
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.NORMAL)
|
|
|
|
def test_unsupported_tag(self):
|
|
self.file.orig_metadata = Metadata()
|
|
self.file.metadata = Metadata({
|
|
'unsupported': 'value'
|
|
})
|
|
self.file.state = File.NORMAL
|
|
|
|
self.file.update(signal=False)
|
|
self.assertEqual(self.file.similarity, 1.0)
|
|
self.assertEqual(self.file.state, File.NORMAL)
|
|
|
|
def test_copy_file_info_tags(self):
|
|
info_tags = {}
|
|
for info in File.FILE_INFO_TAGS:
|
|
info_tags[info] = 'val' + info
|
|
|
|
orig_metadata = Metadata(info_tags)
|
|
orig_metadata['a'] = 'vala'
|
|
metadata = Metadata({
|
|
'~bitrate': 'xxx',
|
|
'b': 'valb',
|
|
})
|
|
self.file._copy_file_info_tags(metadata, orig_metadata)
|
|
for info in File.FILE_INFO_TAGS:
|
|
self.assertEqual('val' + info, metadata[info])
|
|
self.assertEqual('valb', metadata['b'])
|
|
self.assertNotIn('a', metadata)
|