fix crash when RG fields set to null

In general, we convert None values to type-based nulls in packed fields just
as we do for normal fields.
This commit is contained in:
Adrian Sampson 2013-02-24 16:10:18 -08:00
parent fa9d326d39
commit 4a35be5724
3 changed files with 33 additions and 5 deletions

View file

@ -306,18 +306,23 @@ class Packed(object):
"""Makes a packed list of values subscriptable. To access the packed
output after making changes, use packed_thing.items.
"""
def __init__(self, items, packstyle, none_val=0, out_type=int):
def __init__(self, items, packstyle, out_type=int):
"""Create a Packed object for subscripting the packed values in
items. The items are packed using packstyle, which is a value
from the packing enum. none_val is returned from a request when
no suitable value is found in the items. Values are converted to
out_type before they are returned.
from the packing enum. Values are converted to out_type before
they are returned.
"""
self.items = items
self.packstyle = packstyle
self.none_val = none_val
self.out_type = out_type
if out_type is int:
self.none_val = 0
elif out_type is float:
self.none_val = 0.0
else:
self.none_val = None
def __getitem__(self, index):
if not isinstance(index, int):
raise TypeError('index must be an integer')
@ -352,6 +357,10 @@ class Packed(object):
return _safe_cast(self.out_type, out)
def __setitem__(self, index, value):
# Interpret null values.
if value is None:
value = self.none_val
if self.packstyle in (packing.SLASHED, packing.TUPLE, packing.SC):
# SLASHED, TUPLE and SC are always two-item packings
length = 2

View file

@ -12,6 +12,7 @@ Changelog
crashing.
* Add "System Volume Information" (an internal directory found on some
Windows filesystems) to the default ignore list.
* Fix a crash when ReplayGain values were set to null.
* Fix a crash when iTunes Sound Check tags contained invalid data.
* Fix an error when the configuration file (``config.yaml``) is completely
empty.

View file

@ -189,6 +189,7 @@ class ZeroLengthMediaFile(beets.mediafile.MediaFile):
return 0.0
class MissingAudioDataTest(unittest.TestCase):
def setUp(self):
super(MissingAudioDataTest, self).setUp()
path = os.path.join(_common.RSRC, 'full.mp3')
self.mf = ZeroLengthMediaFile(path)
@ -198,6 +199,7 @@ class MissingAudioDataTest(unittest.TestCase):
class TypeTest(unittest.TestCase):
def setUp(self):
super(TypeTest, self).setUp()
path = os.path.join(_common.RSRC, 'full.mp3')
self.mf = beets.mediafile.MediaFile(path)
@ -205,6 +207,22 @@ class TypeTest(unittest.TestCase):
self.mf.year = '2009'
self.assertEqual(self.mf.year, 2009)
def test_set_replaygain_gain_to_none(self):
self.mf.rg_track_gain = None
self.assertEqual(self.mf.rg_track_gain, 0.0)
def test_set_replaygain_peak_to_none(self):
self.mf.rg_track_peak = None
self.assertEqual(self.mf.rg_track_peak, 0.0)
def test_set_year_to_none(self):
self.mf.year = None
self.assertEqual(self.mf.year, 0)
def test_set_track_to_none(self):
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)