mirror of
https://github.com/beetbox/beets.git
synced 2026-01-09 01:15:38 +01:00
mediafile: optionally save ID3v2.3 tags
This commit is contained in:
parent
64dcd283f8
commit
24227d6ef4
2 changed files with 65 additions and 1 deletions
|
|
@ -930,7 +930,18 @@ class MediaFile(object):
|
|||
if self.mgfile.tags is None:
|
||||
self.mgfile.add_tags()
|
||||
|
||||
def save(self):
|
||||
def save(self, id3v23=False):
|
||||
"""Write the object's tags back to the file.
|
||||
|
||||
By default, MP3 files are saved with ID3v2.4 tags. You can use
|
||||
the older ID3v2.3 standard by specifying the `id3v23` option.
|
||||
"""
|
||||
if id3v23 and self.type == 'mp3':
|
||||
id3 = self.mgfile
|
||||
if hasattr(id3, 'tags'):
|
||||
# In case this is an MP3 object, not an ID3 object.
|
||||
id3 = id3.tags
|
||||
id3.update_to_v23()
|
||||
self.mgfile.save()
|
||||
|
||||
def delete(self):
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import _common
|
|||
from _common import unittest
|
||||
import beets.mediafile
|
||||
|
||||
|
||||
class EdgeTest(unittest.TestCase):
|
||||
def test_emptylist(self):
|
||||
# Some files have an ID3 frame that has a list with no elements.
|
||||
|
|
@ -67,6 +68,7 @@ class EdgeTest(unittest.TestCase):
|
|||
f = beets.mediafile.MediaFile(os.path.join(_common.RSRC, 'oldape.ape'))
|
||||
self.assertEqual(f.bitrate, 0)
|
||||
|
||||
|
||||
_sc = beets.mediafile._safe_cast
|
||||
class InvalidValueToleranceTest(unittest.TestCase):
|
||||
def test_packed_integer_with_extra_chars(self):
|
||||
|
|
@ -110,6 +112,7 @@ class InvalidValueToleranceTest(unittest.TestCase):
|
|||
self.assertTrue(isinstance(us, unicode))
|
||||
self.assertTrue(us.startswith(u'caf'))
|
||||
|
||||
|
||||
class SafetyTest(unittest.TestCase):
|
||||
def _exccheck(self, fn, exc, data=''):
|
||||
fn = os.path.join(_common.RSRC, fn)
|
||||
|
|
@ -156,6 +159,7 @@ class SafetyTest(unittest.TestCase):
|
|||
finally:
|
||||
os.unlink(fn)
|
||||
|
||||
|
||||
class SideEffectsTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.empty = os.path.join(_common.RSRC, 'empty.mp3')
|
||||
|
|
@ -166,6 +170,7 @@ 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')
|
||||
|
|
@ -183,10 +188,13 @@ class EncodingTest(unittest.TestCase):
|
|||
new_mf = beets.mediafile.MediaFile(self.path)
|
||||
self.assertEqual(new_mf.label, u'foo\xe8bar')
|
||||
|
||||
|
||||
class ZeroLengthMediaFile(beets.mediafile.MediaFile):
|
||||
@property
|
||||
def length(self):
|
||||
return 0.0
|
||||
|
||||
|
||||
class MissingAudioDataTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
super(MissingAudioDataTest, self).setUp()
|
||||
|
|
@ -197,6 +205,7 @@ class MissingAudioDataTest(unittest.TestCase):
|
|||
del self.mf.mgfile.info.bitrate # Not available directly.
|
||||
self.assertEqual(self.mf.bitrate, 0)
|
||||
|
||||
|
||||
class TypeTest(unittest.TestCase):
|
||||
def setUp(self):
|
||||
super(TypeTest, self).setUp()
|
||||
|
|
@ -223,6 +232,7 @@ class TypeTest(unittest.TestCase):
|
|||
self.mf.track = None
|
||||
self.assertEqual(self.mf.track, 0)
|
||||
|
||||
|
||||
class SoundCheckTest(unittest.TestCase):
|
||||
def test_round_trip(self):
|
||||
data = beets.mediafile._sc_encode(1.0, 1.0)
|
||||
|
|
@ -242,8 +252,51 @@ class SoundCheckTest(unittest.TestCase):
|
|||
self.assertEqual(gain, 0.0)
|
||||
self.assertEqual(peak, 0.0)
|
||||
|
||||
|
||||
class ID3v23Test(unittest.TestCase):
|
||||
def _make_test(self, ext='mp3'):
|
||||
src = os.path.join(_common.RSRC, 'full.{0}'.format(ext))
|
||||
self.path = os.path.join(_common.RSRC, 'test.{0}'.format(ext))
|
||||
shutil.copy(src, self.path)
|
||||
return beets.mediafile.MediaFile(self.path)
|
||||
|
||||
def _delete_test(self):
|
||||
os.remove(self.path)
|
||||
|
||||
def test_v24_year_tag(self):
|
||||
mf = self._make_test()
|
||||
try:
|
||||
mf.year = 2013
|
||||
mf.save(id3v23=False)
|
||||
frame = mf.mgfile['TDRC']
|
||||
self.assertTrue('2013' in str(frame))
|
||||
self.assertTrue('TYER' not in mf.mgfile)
|
||||
finally:
|
||||
self._delete_test()
|
||||
|
||||
def test_v23_year_tag(self):
|
||||
mf = self._make_test()
|
||||
try:
|
||||
mf.year = 2013
|
||||
mf.save(id3v23=True)
|
||||
frame = mf.mgfile['TYER']
|
||||
self.assertTrue('2013' in str(frame))
|
||||
self.assertTrue('TDRC' not in mf.mgfile)
|
||||
finally:
|
||||
self._delete_test()
|
||||
|
||||
def test_v23_on_non_mp3_is_noop(self):
|
||||
mf = self._make_test('m4a')
|
||||
try:
|
||||
mf.year = 2013
|
||||
mf.save(id3v23=True)
|
||||
finally:
|
||||
self._delete_test()
|
||||
|
||||
|
||||
def suite():
|
||||
return unittest.TestLoader().loadTestsFromName(__name__)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main(defaultTest='suite')
|
||||
|
|
|
|||
Loading…
Reference in a new issue