Files
picard/test/test_metadata.py
Laurent Monin 2835732962 match -> match_: match is a statement in Python 3.10+
It doesn't really conflict with variable name but it confuses syntax highlighters (if they are Python 3.10+ aware ofc)
2024-05-25 12:21:31 +02:00

793 lines
31 KiB
Python

# -*- coding: utf-8 -*-
#
# Picard, the next-generation MusicBrainz tagger
#
# Copyright (C) 2017 Sophist-UK
# Copyright (C) 2018, 2020 Wieland Hoffmann
# Copyright (C) 2018-2021 Laurent Monin
# Copyright (C) 2018-2021, 2023 Philipp Wolfer
# Copyright (C) 2020 dukeyin
#
# 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.
from test.picardtestcase import (
PicardTestCase,
create_fake_png,
load_test_json,
)
from test.test_coverart_image import create_image
from picard.acoustid.json_helpers import (
parse_recording as acoustid_parse_recording,
)
from picard.cluster import CLUSTER_COMPARISON_WEIGHTS
from picard.coverart.image import CoverArtImage
from picard.file import FILE_COMPARISON_WEIGHTS
from picard.mbjson import (
release_to_metadata,
track_to_metadata,
)
from picard.metadata import (
MULTI_VALUED_JOINER,
Metadata,
MultiMetadataProxy,
trackcount_score,
weights_from_preferred_countries,
weights_from_preferred_formats,
weights_from_release_type_scores,
)
from picard.track import Track
from picard.util.imagelist import ImageList
from picard.util.tags import PRESERVED_TAGS
settings = {
'write_id3v23': False,
'id3v23_join_with': '/',
'preferred_release_countries': [],
'preferred_release_formats': [],
'standardize_artists': False,
'standardize_instruments': False,
'translate_artist_names': False,
'release_ars': True,
'release_type_scores': [
('Album', 1.0),
('Other', 1.0),
],
}
class CommonTests:
class CommonMetadataTestCase(PicardTestCase):
original = None
tags = []
def setUp(self):
super().setUp()
self.set_config_values(settings)
self.metadata = self.get_metadata_object()
self.metadata.length = 242
self.metadata["single1"] = "single1-value"
self.metadata.add_unique("single2", "single2-value")
self.metadata.add_unique("single2", "single2-value")
self.multi1 = ["multi1-value1", "multi1-value1"]
self.metadata.add("multi1", self.multi1[0])
self.metadata.add("multi1", self.multi1[1])
self.multi2 = ["multi2-value1", "multi2-value2"]
self.metadata["multi2"] = self.multi2
self.multi3 = ["multi3-value1", "multi3-value2"]
self.metadata.set("multi3", self.multi3)
self.metadata["~hidden"] = "hidden-value"
self.metadata_d1 = Metadata({'a': 'b', 'c': 2, 'd': ['x', 'y'], 'x': ''})
self.metadata_d2 = Metadata({'a': 'b', 'c': 2, 'd': ['x', 'y'], 'x': 'z'})
self.metadata_d3 = Metadata({'c': 3, 'd': ['u', 'w'], 'x': 'p'})
@staticmethod
def get_metadata_object():
pass
def tearDown(self):
pass
def test_metadata_setitem(self):
self.assertEqual(["single1-value"], self.metadata.getraw("single1"))
self.assertEqual(["single2-value"], self.metadata.getraw("single2"))
self.assertEqual(self.multi1, self.metadata.getraw("multi1"))
self.assertEqual(self.multi2, self.metadata.getraw("multi2"))
self.assertEqual(self.multi3, self.metadata.getraw("multi3"))
self.assertEqual(["hidden-value"], self.metadata.getraw("~hidden"))
def test_metadata_set_all_values_as_string(self):
for val in (0, 2, True):
str_val = str(val)
self.metadata.set('val1', val)
self.assertEqual([str_val], self.metadata.getraw("val1"))
self.metadata['val2'] = val
self.assertEqual([str_val], self.metadata.getraw("val2"))
del self.metadata['val3']
self.metadata.add('val3', val)
self.assertEqual([str_val], self.metadata.getraw("val3"))
del self.metadata['val4']
self.metadata.add_unique('val4', val)
self.assertEqual([str_val], self.metadata.getraw("val4"))
def test_metadata_get(self):
self.assertEqual("single1-value", self.metadata["single1"])
self.assertEqual("single1-value", self.metadata.get("single1"))
self.assertEqual(["single1-value"], self.metadata.getall("single1"))
self.assertEqual(["single1-value"], self.metadata.getraw("single1"))
self.assertEqual(MULTI_VALUED_JOINER.join(self.multi1), self.metadata["multi1"])
self.assertEqual(MULTI_VALUED_JOINER.join(self.multi1), self.metadata.get("multi1"))
self.assertEqual(self.multi1, self.metadata.getall("multi1"))
self.assertEqual(self.multi1, self.metadata.getraw("multi1"))
self.assertEqual("", self.metadata["nonexistent"])
self.assertEqual(None, self.metadata.get("nonexistent"))
self.assertEqual([], self.metadata.getall("nonexistent"))
self.assertRaises(KeyError, self.metadata.getraw, "nonexistent")
self.assertEqual(self.metadata._store.items(), self.metadata.rawitems())
metadata_items = [(x, z) for (x, y) in self.metadata.rawitems() for z in y]
self.assertEqual(metadata_items, list(self.metadata.items()))
def test_metadata_unset(self):
self.metadata.unset("single1")
self.assertNotIn("single1", self.metadata)
self.assertNotIn("single1", self.metadata.deleted_tags)
self.metadata.unset('unknown_tag')
def test_metadata_pop(self):
self.metadata.pop("single1")
self.assertNotIn("single1", self.metadata)
self.assertIn("single1", self.metadata.deleted_tags)
self.metadata.pop('unknown_tag')
def test_metadata_delete(self):
del self.metadata["single1"]
self.assertNotIn("single1", self.metadata)
self.assertIn("single1", self.metadata.deleted_tags)
def test_metadata_legacy_delete(self):
self.metadata.delete("single1")
self.assertNotIn("single1", self.metadata)
self.assertIn("single1", self.metadata.deleted_tags)
def test_metadata_implicit_delete(self):
self.metadata["single2"] = ""
self.assertNotIn("single2", self.metadata)
self.assertIn("single2", self.metadata.deleted_tags)
self.metadata["unknown"] = ""
self.assertNotIn("unknown", self.metadata)
self.assertNotIn("unknown", self.metadata.deleted_tags)
def test_metadata_undelete(self):
self.metadata.delete("single1")
self.assertNotIn("single1", self.metadata)
self.assertIn("single1", self.metadata.deleted_tags)
self.metadata["single1"] = "value1"
self.assertIn("single1", self.metadata)
self.assertNotIn("single1", self.metadata.deleted_tags)
def test_normalize_tag(self):
self.assertEqual('sometag', Metadata.normalize_tag('sometag'))
self.assertEqual('sometag', Metadata.normalize_tag('sometag:'))
self.assertEqual('sometag', Metadata.normalize_tag('sometag::'))
self.assertEqual('sometag:desc', Metadata.normalize_tag('sometag:desc'))
def test_metadata_tag_trailing_colon(self):
self.metadata['tag:'] = 'Foo'
self.assertIn('tag', self.metadata)
self.assertIn('tag:', self.metadata)
self.assertEqual('Foo', self.metadata['tag'])
self.assertEqual('Foo', self.metadata['tag:'])
del self.metadata['tag']
self.assertNotIn('tag', self.metadata)
self.assertNotIn('tag:', self.metadata)
def test_metadata_copy(self):
m = Metadata()
m["old"] = "old-value"
self.metadata.delete("single1")
m.copy(self.metadata)
self.assertEqual(self.metadata._store, m._store)
self.assertEqual(self.metadata.deleted_tags, m.deleted_tags)
self.assertEqual(self.metadata.length, m.length)
self.assertEqual(self.metadata.images, m.images)
def test_metadata_copy_without_images(self):
m = Metadata()
m.copy(self.metadata, copy_images=False)
self.assertEqual(self.metadata._store, m._store)
self.assertEqual(self.metadata.deleted_tags, m.deleted_tags)
self.assertEqual(self.metadata.length, m.length)
self.assertEqual(ImageList(), m.images)
def test_metadata_init_with_existing_metadata(self):
self.metadata.delete("single1")
cover = CoverArtImage(url='file://file1', data=create_fake_png(b'a'))
self.metadata.images.append(cover)
m = Metadata(self.metadata)
self.assertEqual(self.metadata.length, m.length)
self.assertEqual(self.metadata.deleted_tags, m.deleted_tags)
self.assertEqual(self.metadata.images, m.images)
self.assertEqual(self.metadata._store, m._store)
def test_metadata_update(self):
m = Metadata()
m["old"] = "old-value"
self.metadata.delete("single1")
cover = CoverArtImage(url='file://file1', data=create_fake_png(b'a'))
self.metadata.images.append(cover)
m.update(self.metadata)
self.assertIn("old", m)
self.assertNotIn("single1", m)
self.assertIn("single1", m.deleted_tags)
self.assertEqual("single2-value", m["single2"])
self.assertEqual(self.metadata.length, m.length)
self.assertEqual(self.metadata.deleted_tags, m.deleted_tags)
self.assertEqual(self.metadata.images, m.images)
self.metadata["old"] = "old-value"
self.assertEqual(self.metadata._store, m._store)
def test_metadata_diff(self):
m1 = Metadata({
"foo1": "bar1",
"foo2": "bar2",
"foo3": "bar3",
})
m2 = Metadata(m1)
m1["foo1"] = "baz"
del m1["foo2"]
diff = m1.diff(m2)
self.assertEqual({"foo1": "baz"}, diff)
self.assertEqual(set(["foo2"]), diff.deleted_tags)
def test_metadata_clear(self):
self.metadata.clear()
self.assertEqual(0, len(self.metadata))
def test_metadata_clear_deleted(self):
self.metadata.delete("single1")
self.assertIn("single1", self.metadata.deleted_tags)
self.metadata.clear_deleted()
self.assertNotIn("single1", self.metadata.deleted_tags)
def test_metadata_applyfunc(self):
def func(x):
return x[1:]
self.metadata.apply_func(func)
self.assertEqual("ingle1-value", self.metadata["single1"])
self.assertEqual("ingle1-value", self.metadata.get("single1"))
self.assertEqual(["ingle1-value"], self.metadata.getall("single1"))
self.assertEqual(MULTI_VALUED_JOINER.join(map(func, self.multi1)), self.metadata["multi1"])
self.assertEqual(MULTI_VALUED_JOINER.join(map(func, self.multi1)), self.metadata.get("multi1"))
self.assertEqual(list(map(func, self.multi1)), self.metadata.getall("multi1"))
def test_metadata_applyfunc_preserve_tags(self):
self.assertTrue(len(PRESERVED_TAGS) > 0)
m = Metadata()
m[PRESERVED_TAGS[0]] = 'value1'
m['not_preserved'] = 'value2'
def func(x):
return x[1:]
m.apply_func(func)
self.assertEqual("value1", m[PRESERVED_TAGS[0]])
self.assertEqual("alue2", m['not_preserved'])
def test_metadata_applyfunc_delete_tags(self):
def func(x):
return None
metadata = Metadata(self.metadata)
metadata.apply_func(func)
self.assertEqual(0, len(metadata.rawitems()))
self.assertEqual(self.metadata.keys(), metadata.deleted_tags)
def test_length_score(self):
results = (
(20000, 0, 0.333333333333),
(20000, 10000, 0.666666666667),
(20000, 20000, 1.0),
(20000, 30000, 0.666666666667),
(20000, 40000, 0.333333333333),
(20000, 50000, 0.0),
(20000, None, 0.0),
(None, 2000, 0.0),
(None, None, 0.0),
)
for (a, b, expected) in results:
actual = Metadata.length_score(a, b)
self.assertAlmostEqual(expected, actual,
msg="a={a}, b={b}".format(a=a, b=b))
def test_compare_is_equal(self):
m1 = Metadata()
m1["title"] = "title1"
m1["tracknumber"] = "2"
m1.length = 360
m2 = Metadata()
m2["title"] = "title1"
m2["tracknumber"] = "2"
m2.length = 360
self.assertEqual(m1.compare(m2), m2.compare(m1))
self.assertEqual(m1.compare(m2), 1)
def test_compare_with_ignored(self):
m1 = Metadata()
m1["title"] = "title1"
m1["tracknumber"] = "2"
m1.length = 360
m2 = Metadata()
m2["title"] = "title1"
m2["tracknumber"] = "3"
m2.length = 300
self.assertNotEqual(m1.compare(m2), 1)
self.assertEqual(m1.compare(m2, ignored=['tracknumber', '~length']), 1)
def test_compare_lengths(self):
m1 = Metadata()
m1.length = 360
m2 = Metadata()
m2.length = 300
self.assertAlmostEqual(m1.compare(m2), 0.998)
def test_compare_tracknumber_difference(self):
m1 = Metadata()
m1["tracknumber"] = "1"
m2 = Metadata()
m2["tracknumber"] = "2"
m3 = Metadata()
m3["tracknumber"] = "2"
self.assertEqual(m1.compare(m2), 0)
self.assertEqual(m2.compare(m3), 1)
def test_compare_discnumber_difference(self):
m1 = Metadata()
m1["discnumber"] = "1"
m2 = Metadata()
m2["discnumber"] = "2"
m3 = Metadata()
m3["discnumber"] = "2"
self.assertEqual(m1.compare(m2), 0)
self.assertEqual(m2.compare(m3), 1)
def test_compare_deleted(self):
m1 = Metadata()
m1["artist"] = "TheArtist"
m1["title"] = "title1"
m2 = Metadata()
m2["artist"] = "TheArtist"
m2.delete("title")
self.assertTrue(m1.compare(m2) < 1)
def test_strip_whitespace(self):
m1 = Metadata()
m1["artist"] = " TheArtist "
m1["title"] = "\t\u00A0 tit le1 \r\n"
m1["genre"] = " \t"
m1.strip_whitespace()
self.assertEqual(m1["artist"], "TheArtist")
self.assertEqual(m1["title"], "tit le1")
def test_metadata_mapping_init(self):
d = {'a': 'b', 'c': 2, 'd': ['x', 'y'], 'x': '', 'z': {'u', 'w'}}
deleted_tags = set('c')
m = Metadata(d, deleted_tags=deleted_tags, length=1234)
self.assertIn('a', m)
self.assertEqual(m.getraw('a'), ['b'])
self.assertEqual(m['d'], MULTI_VALUED_JOINER.join(d['d']))
self.assertNotIn('c', m)
self.assertNotIn('length', m)
self.assertIn('c', m.deleted_tags)
self.assertEqual(m.length, 1234)
def test_metadata_mapping_init_zero(self):
m = Metadata(tag1='a', tag2=0, tag3='', tag4=None)
m['tag5'] = 0
m['tag1'] = ''
self.assertIn('tag1', m.deleted_tags)
self.assertEqual(m['tag2'], '0')
self.assertNotIn('tag3', m)
self.assertNotIn('tag4', m)
self.assertEqual(m['tag5'], '0')
def test_metadata_mapping_del(self):
m = self.metadata_d1
self.assertEqual(m.getraw('a'), ['b'])
self.assertNotIn('a', m.deleted_tags)
self.assertNotIn('x', m.deleted_tags)
self.assertRaises(KeyError, m.getraw, 'x')
del m['a']
self.assertRaises(KeyError, m.getraw, 'a')
self.assertIn('a', m.deleted_tags)
# NOTE: historic behavior of Metadata.delete()
# an attempt to delete an non-existing tag, will add it to the list
# of deleted tags
# so this will not raise a KeyError
# as is it differs from dict or even defaultdict behavior
del m['unknown']
self.assertIn('unknown', m.deleted_tags)
def test_metadata_mapping_iter(self):
self.assertEqual(set(self.metadata_d1), {'a', 'c', 'd'})
def test_metadata_mapping_keys(self):
self.assertEqual(set(self.metadata_d1.keys()), {'a', 'c', 'd'})
def test_metadata_mapping_values(self):
self.assertEqual(set(self.metadata_d1.values()), {'b', '2', 'x; y'})
def test_metadata_mapping_len(self):
m = self.metadata_d1
self.assertEqual(len(m), 3)
del m['x']
self.assertEqual(len(m), 3)
del m['c']
self.assertEqual(len(m), 2)
def _check_mapping_update(self, m):
self.assertEqual(m['a'], 'b')
self.assertEqual(m['c'], '3')
self.assertEqual(m.getraw('d'), ['u', 'w'])
self.assertEqual(m['x'], '')
self.assertIn('x', m.deleted_tags)
def test_metadata_mapping_update(self):
# update from Metadata
m = self.metadata_d2
m2 = self.metadata_d3
del m2['x']
m.update(m2)
self._check_mapping_update(m)
def test_metadata_mapping_update_dict(self):
# update from dict
m = self.metadata_d2
d2 = {'c': 3, 'd': ['u', 'w'], 'x': ''}
m.update(d2)
self._check_mapping_update(m)
def test_metadata_mapping_update_tuple(self):
# update from tuple
m = self.metadata_d2
d2 = (('c', 3), ('d', ['u', 'w']), ('x', ''))
m.update(d2)
self._check_mapping_update(m)
def test_metadata_mapping_update_dictlike(self):
# update from kwargs
m = self.metadata_d2
m.update(c=3, d=['u', 'w'], x='')
self._check_mapping_update(m)
def test_metadata_mapping_update_noparam(self):
# update without parameter
m = self.metadata_d2
self.assertRaises(TypeError, m.update)
self.assertEqual(m['a'], 'b')
def test_metadata_mapping_update_intparam(self):
# update without parameter
m = self.metadata_d2
self.assertRaises(TypeError, m.update, 123)
def test_metadata_mapping_update_strparam(self):
# update without parameter
m = self.metadata_d2
self.assertRaises(ValueError, m.update, 'abc')
def test_metadata_mapping_update_kw(self):
m = Metadata(tag1='a', tag2='b')
m.update(tag1='c')
self.assertEqual(m['tag1'], 'c')
self.assertEqual(m['tag2'], 'b')
m.update(tag2='')
self.assertIn('tag2', m.deleted_tags)
def test_metadata_mapping_update_kw_del(self):
m = Metadata(tag1='a', tag2='b')
del m['tag1']
m2 = Metadata(tag1='c', tag2='d')
del m2['tag2']
m.update(m2)
self.assertEqual(m['tag1'], 'c')
self.assertNotIn('tag2', m)
self.assertNotIn('tag1', m.deleted_tags)
self.assertIn('tag2', m.deleted_tags)
def test_metadata_mapping_images(self):
image1 = create_image(b'A', comment='A')
image2 = create_image(b'B', comment='B')
m1 = Metadata(a='b', length=1234, images=[image1])
self.assertEqual(m1.images[0], image1)
self.assertEqual(len(m1), 2) # one tag, one image
m1.images.append(image2)
self.assertEqual(m1.images[1], image2)
m1.images.pop(0)
self.assertEqual(m1.images[0], image2)
m2 = Metadata(a='c', length=4567, images=[image1])
m1.update(m2)
self.assertEqual(m1.images[0], image1)
m1.images.pop(0)
self.assertEqual(len(m1), 1) # one tag, zero image
self.assertFalse(m1.images)
def test_metadata_mapping_iterable(self):
m = Metadata(tag_tuple=('a', 0))
m['tag_set'] = {'c', 'd'}
m['tag_dict'] = {'e': 1, 'f': 2}
m['tag_str'] = 'gh'
self.assertIn('0', m.getraw('tag_tuple'))
self.assertIn('c', m.getraw('tag_set'))
self.assertIn('e', m.getraw('tag_dict'))
self.assertIn('gh', m.getraw('tag_str'))
def test_compare_to_release(self):
release = load_test_json('release.json')
metadata = Metadata()
release_to_metadata(release, metadata)
match_ = metadata.compare_to_release(release, CLUSTER_COMPARISON_WEIGHTS)
self.assertEqual(1.0, match_.similarity)
self.assertEqual(release, match_.release)
def test_compare_to_release_with_score(self):
release = load_test_json('release.json')
metadata = Metadata()
release_to_metadata(release, metadata)
for score, sim in ((42, 0.42), ('42', 0.42), ('foo', 1.0), (None, 1.0)):
release['score'] = score
match_ = metadata.compare_to_release(release, CLUSTER_COMPARISON_WEIGHTS)
self.assertEqual(sim, match_.similarity)
def test_compare_to_release_parts_totaltracks(self):
release = load_test_json('release_multidisc.json')
metadata = Metadata()
weights = {"totaltracks": 30}
release_to_metadata(release, metadata)
for totaltracks, sim in ((4, 1.0), (3, 1.0), (2, 0.3), (5, 0.0)):
metadata['totaltracks'] = totaltracks
parts = metadata.compare_to_release_parts(release, weights)
self.assertIn((sim, 30), parts)
def test_compare_to_release_parts_totalalbumtracks(self):
release = load_test_json('release_multidisc.json')
metadata = Metadata()
weights = {"totalalbumtracks": 30}
release_to_metadata(release, metadata)
for totaltracks, sim in ((7, 1.0), (6, 0.3), (8, 0.0)):
metadata['~totalalbumtracks'] = totaltracks
parts = metadata.compare_to_release_parts(release, weights)
self.assertIn((sim, 30), parts)
def test_compare_to_release_parts_totalalbumtracks_totaltracks_fallback(self):
release = load_test_json('release_multidisc.json')
metadata = Metadata()
weights = {"totalalbumtracks": 30}
release_to_metadata(release, metadata)
for totaltracks, sim in ((7, 1.0), (6, 0.3), (8, 0.0)):
metadata['totaltracks'] = totaltracks
parts = metadata.compare_to_release_parts(release, weights)
self.assertIn((sim, 30), parts)
def test_trackcount_score(self):
self.assertEqual(1.0, trackcount_score(5, 5))
self.assertEqual(0.0, trackcount_score(6, 5))
self.assertEqual(0.3, trackcount_score(4, 5))
def test_weights_from_release_type_scores(self):
release = load_test_json('release.json')
parts = []
weights_from_release_type_scores(parts, release, {'Album': 0.75}, 666)
self.assertEqual(
parts[0],
(0.75, 666)
)
weights_from_release_type_scores(parts, release, {}, 666)
self.assertEqual(
parts[1],
(0.5, 666)
)
def test_weights_from_release_type_scores_no_type(self):
release = load_test_json('release_no_type.json')
parts = []
weights_from_release_type_scores(parts, release, {'Other': 0.75}, 123)
self.assertEqual(
parts[0],
(0.75, 123)
)
weights_from_release_type_scores(parts, release, {}, 123)
self.assertEqual(
parts[1],
(0.5, 123)
)
def test_preferred_countries(self):
release = load_test_json('release.json')
parts = []
weights_from_preferred_countries(parts, release, [], 666)
self.assertFalse(parts)
weights_from_preferred_countries(parts, release, ['FR'], 666)
self.assertEqual(parts[0], (0.0, 666))
weights_from_preferred_countries(parts, release, ['GB'], 666)
self.assertEqual(parts[1], (1.0, 666))
def test_preferred_formats(self):
release = load_test_json('release.json')
parts = []
weights_from_preferred_formats(parts, release, [], 777)
self.assertFalse(parts)
weights_from_preferred_formats(parts, release, ['Digital Media'], 777)
self.assertEqual(parts[0], (0.0, 777))
weights_from_preferred_formats(parts, release, ['12" Vinyl'], 777)
self.assertEqual(parts[1], (1.0, 777))
def test_compare_to_track(self):
track_json = load_test_json('track.json')
track = Track(track_json['id'])
track_to_metadata(track_json, track)
match_ = track.metadata.compare_to_track(track_json, FILE_COMPARISON_WEIGHTS)
self.assertEqual(1.0, match_.similarity)
self.assertEqual(track_json, match_.track)
def test_compare_to_track_with_score(self):
track_json = load_test_json('track.json')
track = Track(track_json['id'])
track_to_metadata(track_json, track)
for score, sim in ((42, 0.42), ('42', 0.42), ('foo', 1.0), (None, 1.0)):
track_json['score'] = score
match_ = track.metadata.compare_to_track(track_json, FILE_COMPARISON_WEIGHTS)
self.assertEqual(sim, match_.similarity)
def test_compare_to_track_is_video(self):
recording = load_test_json('recording_video_null.json')
m = Metadata()
match_ = m.compare_to_track(recording, {'isvideo': 1})
self.assertEqual(1.0, match_.similarity)
m['~video'] = '1'
match_ = m.compare_to_track(recording, {'isvideo': 1})
self.assertEqual(0.0, match_.similarity)
recording['video'] = True
match_ = m.compare_to_track(recording, {'isvideo': 1})
self.assertEqual(1.0, match_.similarity)
def test_compare_to_track_full(self):
recording = load_test_json('recording_video_null.json')
m = Metadata({
'artist': 'Tim Green',
'release': 'Eastbound Silhouette',
'date': '2022',
'title': 'Lune',
'totaltracks': '6',
'albumartist': 'Tim Green',
'tracknumber': '4',
})
match_ = m.compare_to_track(recording, FILE_COMPARISON_WEIGHTS)
self.assertGreaterEqual(match_.similarity, 0.8)
self.assertEqual(recording, match_.track)
self.assertEqual(recording['releases'][0], match_.release)
def test_compare_to_track_without_releases(self):
self.set_config_values({
'release_type_scores': [('Compilation', 0.6), ('Other', 0.6)]
})
track_json = acoustid_parse_recording(load_test_json('acoustid.json'))
track = Track(track_json['id'])
track.metadata.update({
'album': 'x',
'artist': 'Ed Sheeran',
'title': 'Nina',
})
track.metadata.length = 225000
m1 = track.metadata.compare_to_track(track_json, FILE_COMPARISON_WEIGHTS)
del track_json['releases']
m2 = track.metadata.compare_to_track(track_json, FILE_COMPARISON_WEIGHTS)
self.assertGreater(m1.similarity, m2.similarity,
'Matching score for release with recordings must be higher then for release without')
class MetadataTest(CommonTests.CommonMetadataTestCase):
@staticmethod
def get_metadata_object():
return Metadata()
class MultiMetadataProxyAsMetadataTest(CommonTests.CommonMetadataTestCase):
@staticmethod
def get_metadata_object():
return MultiMetadataProxy(Metadata())
class MultiMetadataProxyTest(PicardTestCase):
def setUp(self):
super().setUp()
self.m1 = Metadata({
"key1": "m1.val1",
"key2": "m1.val2",
})
self.m2 = Metadata({
"key2": "m2.val2",
"key3": "m2.val3",
})
self.m3 = Metadata({
"key2": "m3.val2",
"key4": "m3.val4",
})
def test_get_attribute(self):
mp = MultiMetadataProxy(self.m1, self.m2, self.m3)
self.assertEqual(mp.deleted_tags, self.m1.deleted_tags)
def test_gettitem(self):
mp = MultiMetadataProxy(self.m1, self.m2, self.m3)
self.assertEqual("m1.val1", mp["key1"])
self.assertEqual("m1.val2", mp["key2"])
self.assertEqual("m2.val3", mp["key3"])
self.assertEqual("m3.val4", mp["key4"])
def test_settitem(self):
orig_m2 = Metadata(self.m2)
mp = MultiMetadataProxy(self.m1, self.m2, self.m3)
mp["key1"] = "foo1"
mp["key2"] = "foo2"
mp["key3"] = "foo3"
mp["key4"] = "foo4"
mp["key5"] = "foo5"
self.assertEqual("foo1", self.m1["key1"])
self.assertEqual("foo2", self.m1["key2"])
self.assertEqual("foo3", self.m1["key3"])
self.assertEqual("foo4", self.m1["key4"])
self.assertEqual("foo5", self.m1["key5"])
self.assertEqual(orig_m2, self.m2)
def test_delitem(self):
orig_m2 = Metadata(self.m2)
mp = MultiMetadataProxy(self.m1, self.m2, self.m3)
del mp["key2"]
del mp["key3"]
self.assertIn("key2", self.m1.deleted_tags)
self.assertIn("key3", self.m1.deleted_tags)
self.assertEqual(orig_m2, self.m2)