Remove null normalization for replaygain.

A `None` value for replagain fields is different from a `0.0` value [1].

[1]: https://github.com/sampsyo/beets/issues/157#issuecomment-39521322
This commit is contained in:
Thomas Scholtes 2014-04-10 22:02:24 +02:00
parent c27d26ddbf
commit 7b954d9999
5 changed files with 69 additions and 22 deletions

View file

@ -55,6 +55,7 @@ class Type(object):
type, normalize the value to have the appropriate type. This
base implementation only reinterprets `None`.
"""
# TODO gradually remove the normalization of None.
if value is None:
return self.null
else:
@ -131,6 +132,12 @@ class Float(Type):
return 0.0
class NullFloat(Float):
"""Same as `Float`, but does not normalize `None` to `0.0`.
"""
null = None
class String(Type):
"""A Unicode string type.
"""

View file

@ -245,10 +245,10 @@ class Item(LibModel):
'albumdisambig': types.String(),
'disctitle': types.String(),
'encoder': types.String(),
'rg_track_gain': types.Float(),
'rg_track_peak': types.Float(),
'rg_album_gain': types.Float(),
'rg_album_peak': types.Float(),
'rg_track_gain': types.NullFloat(),
'rg_track_peak': types.NullFloat(),
'rg_album_gain': types.NullFloat(),
'rg_album_peak': types.NullFloat(),
'original_year': types.PaddedInt(4),
'original_month': types.PaddedInt(2),
'original_day': types.PaddedInt(2),
@ -628,8 +628,8 @@ class Album(LibModel):
'albumstatus': types.String(),
'media': types.String(),
'albumdisambig': types.String(),
'rg_album_gain': types.Float(),
'rg_album_peak': types.Float(),
'rg_album_gain': types.NullFloat(),
'rg_album_peak': types.NullFloat(),
'original_year': types.PaddedInt(4),
'original_month': types.PaddedInt(2),
'original_day': types.PaddedInt(2),

View file

@ -16,7 +16,7 @@ import sys
import os
import os.path
import shutil
import tempfile
from tempfile import mkdtemp, mkstemp
from glob import glob
from contextlib import contextmanager
from StringIO import StringIO
@ -36,7 +36,7 @@ def controlStdin(input=None):
"""Sends ``input`` to stdin.
>>> with controlStdin('yes'):
... in = input()
... input()
'yes'
"""
org = sys.stdin
@ -47,6 +47,7 @@ def controlStdin(input=None):
finally:
sys.stdin = org
class TestHelper(object):
"""Helper mixin for high-level cli and plugin tests.
@ -77,7 +78,7 @@ class TestHelper(object):
Make sure you call ``teardown_beets()`` afterwards.
"""
self.temp_dir = tempfile.mkdtemp()
self.temp_dir = mkdtemp()
os.environ['BEETSDIR'] = self.temp_dir
self.config = beets.config
@ -152,5 +153,15 @@ class TestHelper(object):
items.append(item)
return items
def create_file_fixture(self, pattern='*.mp3'):
"""Copies a file matching the glob pattern to a temporary
location and returns the path.
"""
src = glob(os.path.join(_common.RSRC, pattern))[0]
handle, path = mkstemp()
os.close(handle)
shutil.copy(src, path)
return path
def run_command(self, *args):
beets.ui._raw_main(list(args))

View file

@ -90,25 +90,25 @@ class ReplayGainCliTestBase(object):
self._reset_replaygain(item)
def _reset_replaygain(self, item):
item['rg_track_peak'] = 0
item['rg_track_gain'] = 0
item['rg_album_gain'] = 0
item['rg_album_gain'] = 0
item['rg_track_peak'] = None
item['rg_track_gain'] = None
item['rg_album_gain'] = None
item['rg_album_gain'] = None
item.write()
item.store()
def test_cli_saves_track_gain(self):
for item in self.lib.items():
self.assertEqual(item.rg_track_peak, 0.0)
self.assertEqual(item.rg_track_gain, 0.0)
self.assertIsNone(item.rg_track_peak)
self.assertIsNone(item.rg_track_gain)
mediafile = MediaFile(item.path)
self.assertEqual(mediafile.rg_track_peak, 0.0)
self.assertEqual(mediafile.rg_track_gain, 0.0)
self.assertIsNone(mediafile.rg_track_peak)
self.assertIsNone(mediafile.rg_track_gain)
ui._raw_main(['replaygain'])
for item in self.lib.items():
self.assertNotEqual(item.rg_track_peak, 0.0)
self.assertNotEqual(item.rg_track_gain, 0.0)
self.assertIsNotNone(item.rg_track_peak)
self.assertIsNotNone(item.rg_track_gain)
mediafile = MediaFile(item.path)
self.assertAlmostEqual(
mediafile.rg_track_peak, item.rg_track_peak, places=6)
@ -127,8 +127,8 @@ class ReplayGainCliTestBase(object):
def test_cli_saves_album_gain_to_file(self):
for item in self.lib.items():
mediafile = MediaFile(item.path)
self.assertEqual(mediafile.rg_album_peak, 0.0)
self.assertEqual(mediafile.rg_album_gain, 0.0)
self.assertIsNone(mediafile.rg_album_peak)
self.assertIsNone(mediafile.rg_album_gain)
ui._raw_main(['replaygain', '-a'])

View file

@ -1,11 +1,21 @@
"""Tests for the 'zero' plugin"""
from _common import unittest
from helper import TestHelper
from beets.library import Item
from beets import config
from beetsplug.zero import ZeroPlugin
from beets.mediafile import MediaFile
class ZeroPluginTest(unittest.TestCase):
class ZeroPluginTest(unittest.TestCase, TestHelper):
def tearDown(self):
config.clear()
self.unload_plugins()
def test_no_patterns(self):
i = Item(
comments='test comment',
@ -39,6 +49,25 @@ class ZeroPluginTest(unittest.TestCase):
self.assertEqual(i.comments, '')
self.assertEqual(i.year, 2012)
def test_delete_replaygain_tag(self):
path = self.create_file_fixture()
item = Item.from_path(path)
item.rg_track_peak = 0.0
item.write()
mediafile = MediaFile(item.path)
self.assertIsNotNone(mediafile.rg_track_peak)
config['zero'] = {
'fields': ['rg_track_peak'],
}
self.load_plugins('zero')
item.write()
mediafile = MediaFile(item.path)
self.assertIsNone(mediafile.rg_track_peak)
def suite():
return unittest.TestLoader().loadTestsFromName(__name__)