MPEG-4 Unicode freeform frames are now encoded as UTF-8 bytes

This commit is contained in:
Adrian Sampson 2011-07-31 23:03:19 -07:00
parent ec125b701f
commit b63d6c858b
3 changed files with 33 additions and 4 deletions

View file

@ -382,6 +382,11 @@ class MediaField(object):
if style.packing:
out = Packed(out, style.packing)[style.pack_pos]
# MPEG-4 freeform frames are (should be?) encoded as UTF-8.
if obj.type == 'mp4' and style.key.startswith('----:') and \
isinstance(out, str):
out = out.decode('utf8')
return _safe_cast(self.out_type, out)
@ -410,8 +415,8 @@ class MediaField(object):
out = u''
# We trust that packed values are handled above.
# convert to correct storage type (irrelevant for
# packed values)
# Convert to correct storage type (irrelevant for
# packed values).
if style.as_type == unicode:
if out is None:
out = u''
@ -429,7 +434,13 @@ class MediaField(object):
elif style.as_type in (bool, str):
out = style.as_type(out)
# store the data
# MPEG-4 "freeform" (----) frames must be encoded as UTF-8
# byte strings.
if obj.type == 'mp4' and style.key.startswith('----:') and \
isinstance(out, unicode):
out = out.encode('utf8')
# Store the data.
self._storedata(obj, out, style)
class CompositeDateField(object):

View file

@ -180,7 +180,7 @@ CHAR_REPLACE = [
(re.compile(r'[\\/\?]|^\.'), '_'),
(re.compile(r':'), '-'),
]
CHAR_REPLACE_WINDOWS = re.compile('["\*<>\|]|^\.|\.$| +$'), '_'
CHAR_REPLACE_WINDOWS = re.compile(r'["\*<>\|]|^\.|\.$| +$'), '_'
def sanitize_path(path, pathmod=None):
"""Takes a path and makes sure that it is legal. Returns a new path.
Only works with fragments; won't work reliably on Windows when a

View file

@ -17,6 +17,7 @@
import unittest
import os
import shutil
import _common
import beets.mediafile
@ -149,6 +150,23 @@ class SideEffectsTest(unittest.TestCase):
new_mtime = os.stat(self.empty).st_mtime
self.assertEqual(old_mtime, new_mtime)
class EncodingTest(unittest.TestCase):
def setUp(self):
src = os.path.join(_common.RSRC, 'full.m4a')
self.path = os.path.join(_common.RSRC, 'test.m4a')
shutil.copy(src, self.path)
self.mf = beets.mediafile.MediaFile(self.path)
def tearDown(self):
os.remove(self.path)
def test_unicode_label_in_m4a(self):
self.mf.label = u'foo\xe8bar'
self.mf.save()
new_mf = beets.mediafile.MediaFile(self.path)
self.assertEqual(new_mf.label, u'foo\xe8bar')
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)