PICARD-1592: Preserve case for APEv2 tags

When reading APEv2 tags case insensitive, preserve existing casing.
This commit is contained in:
Philipp Wolfer
2019-11-03 19:21:37 +01:00
parent 4a86549b50
commit 0854b91c90
2 changed files with 33 additions and 6 deletions

View File

@@ -112,21 +112,26 @@ class APEv2File(File):
}
__rtranslate = dict([(v.lower(), k) for k, v in __translate.items()])
def __init__(self, filename):
super().__init__(filename)
self.__casemap = {}
def _load(self, filename):
log.debug("Loading file %r", filename)
self.__casemap = {}
file = self._File(encode_filename(filename))
metadata = Metadata()
if file.tags:
for origname, values in file.tags.items():
origname = origname.lower()
name_lower = origname.lower()
if (values.kind == mutagen.apev2.BINARY
and origname.startswith("cover art")):
and name_lower.startswith("cover art")):
if b'\0' in values.value:
descr, data = values.value.split(b'\0', 1)
try:
coverartimage = TagCoverArtImage(
file=filename,
tag=origname,
tag=name_lower,
data=data,
)
except CoverArtImageError as e:
@@ -139,7 +144,7 @@ class APEv2File(File):
if values.kind != mutagen.apev2.TEXT:
continue
for value in values:
name = origname
name = name_lower
if name == "year":
name = "date"
value = sanitize_date(value)
@@ -164,6 +169,7 @@ class APEv2File(File):
value = value[:start]
elif name in self.__rtranslate:
name = self.__rtranslate[name]
self.__casemap[name] = origname
metadata.add(name, value)
self._info(metadata, file)
return metadata
@@ -238,7 +244,9 @@ class APEv2File(File):
del tags[real_name]
def _get_tag_name(self, name):
if name.startswith('lyrics:'):
if name in self.__casemap:
return self.__casemap[name]
elif name.startswith('lyrics:'):
return 'Lyrics'
elif name == 'date':
return 'Year'

View File

@@ -87,6 +87,25 @@ class CommonApeTests:
self._read_case_insensitive_tag('tracknumber', 'Track')
self._read_case_insensitive_tag('discnumber', 'Disc')
@skipUnlessTestfile
def test_ci_tags_preserve_case(self):
# Ensure values are not duplicated on repeated save and are saved
# case preserving.
for name in ('CUStom', 'ARtist'):
tags = {}
tags[name] = 'foo'
save_raw(self.filename, tags)
loaded_metadata = load_metadata(self.filename)
loaded_metadata[name.lower()] = 'bar'
save_metadata(self.filename, loaded_metadata)
raw_metadata = dict(load_raw(self.filename))
self.assertIn(name, raw_metadata)
self.assertEqual(
raw_metadata[name],
loaded_metadata[name.lower()])
self.assertEqual(1, len(raw_metadata[name]))
self.assertNotIn(name.upper(), raw_metadata)
def _read_case_insensitive_tag(self, name, ape_name):
upper_ape_name = ape_name.upper()
metadata = {
@@ -97,7 +116,7 @@ class CommonApeTests:
self.assertEqual(metadata[upper_ape_name], loaded_metadata[name])
save_metadata(self.filename, loaded_metadata)
raw_metadata = load_raw(self.filename)
self.assertIn(ape_name, raw_metadata.keys())
self.assertIn(upper_ape_name, raw_metadata.keys())
self.assertEqual(metadata[upper_ape_name], raw_metadata[ape_name])