From a2a84ac8e68dd0ed13b7e0a8a4be40c24b2e6b20 Mon Sep 17 00:00:00 2001 From: Laurent Monin Date: Wed, 9 Apr 2014 14:09:10 +0200 Subject: [PATCH] Convert `release_type_scores` option to `ListOption` We had a space-separated list of name,value tuples ("Album 0.5 Other 0.4"), and two helper functions to load and save data in the correct format (`load_release_type_scores` and `save_release_type_scores`). Since option is converted to recently-introduced ListOption, data is now saved as a list of tuples, eventually converted to dict when needed. It simplifies code, and also prevents an issue if it comes we have a release group type with a space in its name. An upgrade hook was added to handle this change on Picard upgrade. --- picard/__init__.py | 2 +- picard/config_upgrade.py | 19 +++++++++++++++++++ picard/metadata.py | 3 +-- picard/ui/options/releases.py | 17 ++++++----------- picard/util/__init__.py | 16 ---------------- test/test_utils.py | 30 ------------------------------ 6 files changed, 27 insertions(+), 60 deletions(-) diff --git a/picard/__init__.py b/picard/__init__.py index 1f13df46f..8c0f42ada 100644 --- a/picard/__init__.py +++ b/picard/__init__.py @@ -22,7 +22,7 @@ import re PICARD_APP_NAME = "Picard" PICARD_ORG_NAME = "MusicBrainz" -PICARD_VERSION = (1, 3, 0, 'dev', 3) +PICARD_VERSION = (1, 3, 0, 'dev', 4) class VersionError(Exception): diff --git a/picard/config_upgrade.py b/picard/config_upgrade.py index 463999853..fac1f9184 100644 --- a/picard/config_upgrade.py +++ b/picard/config_upgrade.py @@ -118,10 +118,29 @@ def upgrade_to_v1_3_0_dev_3(): _s[opt] = _s.raw_value(opt).split(sep) +def upgrade_to_v1_3_0_dev_4(): + """Option "release_type_scores" is now a list of tuples + """ + def load_release_type_scores(setting): + scores = [] + values = setting.split() + for i in range(0, len(values), 2): + try: + score = float(values[i + 1]) + except IndexError: + score = 0.0 + scores.append((values[i], score)) + return scores + + opt = "release_type_scores" + _s[opt] = load_release_type_scores(_s.raw_value(opt)) + + def upgrade_config(): cfg = config._config cfg.register_upgrade_hook(upgrade_to_v1_0_0_final_0) cfg.register_upgrade_hook(upgrade_to_v1_3_0_dev_1) cfg.register_upgrade_hook(upgrade_to_v1_3_0_dev_2) cfg.register_upgrade_hook(upgrade_to_v1_3_0_dev_3) + cfg.register_upgrade_hook(upgrade_to_v1_3_0_dev_4) cfg.run_upgrade_hooks(log.debug) diff --git a/picard/metadata.py b/picard/metadata.py index e7af4d78f..c6bd757ab 100644 --- a/picard/metadata.py +++ b/picard/metadata.py @@ -32,7 +32,6 @@ from picard.plugin import ExtensionPoint from picard.similarity import similarity2 from picard.util import ( encode_filename, - load_release_type_scores, mimetype as mime, replace_non_ascii, replace_win32_incompat, @@ -288,7 +287,7 @@ class Metadata(dict): parts.append((score, weights["format"])) if "releasetype" in weights: - type_scores = load_release_type_scores(config.setting["release_type_scores"]) + type_scores = dict(config.setting["release_type_scores"]) if 'release_group' in release.children and 'type' in release.release_group[0].attribs: release_type = release.release_group[0].type score = type_scores.get(release_type, type_scores.get('Other', 0.5)) diff --git a/picard/ui/options/releases.py b/picard/ui/options/releases.py index e95808691..ca77576ce 100644 --- a/picard/ui/options/releases.py +++ b/picard/ui/options/releases.py @@ -21,7 +21,6 @@ from operator import itemgetter from locale import strcoll from PyQt4 import QtCore, QtGui from picard import config -from picard.util import load_release_type_scores, save_release_type_scores from picard.ui.options import OptionsPage, register_options_page from picard.ui.ui_options_releases import Ui_ReleasesOptionsPage from picard.const import (RELEASE_COUNTRIES, @@ -32,11 +31,7 @@ from picard.i18n import ugettext_attr _DEFAULT_SCORE = 0.5 -_release_type_scores = save_release_type_scores(dict([(g, _DEFAULT_SCORE) for g - in - RELEASE_PRIMARY_GROUPS.keys() - + - RELEASE_SECONDARY_GROUPS.keys()])) +_release_type_scores = [(g, _DEFAULT_SCORE) for g in RELEASE_PRIMARY_GROUPS.keys() + RELEASE_SECONDARY_GROUPS.keys()] class ReleaseTypeScore: @@ -94,7 +89,7 @@ class ReleasesOptionsPage(OptionsPage): ACTIVE = True options = [ - config.TextOption("setting", "release_type_scores", _release_type_scores), + config.ListOption("setting", "release_type_scores", _release_type_scores), config.ListOption("setting", "preferred_release_countries", []), config.ListOption("setting", "preferred_release_formats", []), ] @@ -142,7 +137,7 @@ class ReleasesOptionsPage(OptionsPage): self.ui.preferred_format_list.setSelectionMode(QtGui.QAbstractItemView.ExtendedSelection) def load(self): - scores = load_release_type_scores(config.setting["release_type_scores"]) + scores = dict(config.setting["release_type_scores"]) for (release_type, release_type_slider) in self._release_type_sliders.iteritems(): release_type_slider.setValue(scores.get(release_type, _DEFAULT_SCORE)) @@ -153,10 +148,10 @@ class ReleasesOptionsPage(OptionsPage): self.ui.format_list, self.ui.preferred_format_list) def save(self): - scores = {} + scores = [] for (release_type, release_type_slider) in self._release_type_sliders.iteritems(): - scores[release_type] = release_type_slider.value() - config.setting["release_type_scores"] = save_release_type_scores(scores) + scores.append((release_type, release_type_slider.value())) + config.setting["release_type_scores"] = scores self._save_list_items("preferred_release_countries", self.ui.preferred_country_list) self._save_list_items("preferred_release_formats", self.ui.preferred_format_list) diff --git a/picard/util/__init__.py b/picard/util/__init__.py index 5213f7a4a..f9545be73 100644 --- a/picard/util/__init__.py +++ b/picard/util/__init__.py @@ -267,22 +267,6 @@ def rot13(input): return u''.join(unichr(rot_13.encoding_map.get(ord(c), ord(c))) for c in input) -def load_release_type_scores(setting): - scores = {} - values = setting.split() - for i in range(0, len(values), 2): - try: - score = float(values[i + 1]) - except IndexError: - score = 0.0 - scores[values[i]] = score - return scores - - -def save_release_type_scores(scores): - return " ".join(["%s %.2f" % v for v in scores.iteritems()]) - - def parse_amazon_url(url): """Extract host and asin from an amazon url. It returns a dict with host and asin keys on success, None else diff --git a/test/test_utils.py b/test/test_utils.py index 13462a7a0..2b788f67c 100644 --- a/test/test_utils.py +++ b/test/test_utils.py @@ -92,36 +92,6 @@ class FormatTimeTest(unittest.TestCase): self.assertEqual("2:59", util.format_time(179499)) -class LoadReleaseTypeScoresTest(unittest.TestCase): - - def test_valid(self): - release_type_score_config = "Album 1.0 Single 0.5 EP 0.5 Compilation 0.5 Soundtrack 0.5 Spokenword 0.5 Interview 0.2 Audiobook 0.0 Live 0.5 Remix 0.4 Other 0.0" - release_type_scores = util.load_release_type_scores(release_type_score_config) - self.assertEqual(1.0, release_type_scores["Album"]) - self.assertEqual(0.5, release_type_scores["Single"]) - self.assertEqual(0.2, release_type_scores["Interview"]) - self.assertEqual(0.0, release_type_scores["Audiobook"]) - self.assertEqual(0.4, release_type_scores["Remix"]) - - def test_invalid(self): - release_type_score_config = "Album 1.0 Other" - release_type_scores = util.load_release_type_scores(release_type_score_config) - self.assertEqual(1.0, release_type_scores["Album"]) - self.assertEqual(0.0, release_type_scores["Other"]) - - -class SaveReleaseTypeScoresTest(unittest.TestCase): - - def test(self): - expected = "Album 1.00 Single 0.50 Other 0.00" - scores = {"Album": 1.0, "Single": 0.5, "Other": 0.0} - saved_scores = util.save_release_type_scores(scores) - self.assertTrue("Album 1.00" in saved_scores) - self.assertTrue("Single 0.50" in saved_scores) - self.assertTrue("Other 0.00" in saved_scores) - self.assertEqual(6, len(saved_scores.split())) - - class HiddenPathTest(unittest.TestCase): def test(self):