diff --git a/NEWS b/NEWS index 9adafb9b9..b68096837 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,7 @@ 1.0b8 ----- +* Better support for singleton (non-album) tracks. The "singleton" path + format can be used to customize where these tracks are stored. * The "distance" number, which quantifies how different an album's current and proposed metadata are, is now displayed as "similarity" instead. This should be less noisy and confusing; you'll now see diff --git a/beets/library.py b/beets/library.py index b50e91096..37f56873e 100644 --- a/beets/library.py +++ b/beets/library.py @@ -900,7 +900,13 @@ class Library(BaseLibrary): pathmod = pathmod or os.path # Use a path format based on the album type, if available. - if item.albumtype and item.albumtype in self.path_formats: + if not item.album_id: + # Singleton track. Never use the "album" formats. + if 'singleton' in self.path_formats: + path_format = self.path_formats['singleton'] + else: + path_format = self.path_formats['default'] + elif item.albumtype and item.albumtype in self.path_formats: path_format = self.path_formats[item.albumtype] elif item.comp and 'comp' in self.path_formats: path_format = self.path_formats['comp'] diff --git a/beets/ui/__init__.py b/beets/ui/__init__.py index 62b71cb8b..bcd41f620 100644 --- a/beets/ui/__init__.py +++ b/beets/ui/__init__.py @@ -38,6 +38,7 @@ DEFAULT_DIRECTORY = '~/Music' DEFAULT_PATH_FORMATS = { 'default': '$albumartist/$album/$track $title', 'comp': 'Compilations/$album/$track $title', + 'singleton': 'Non-Album/$artist/$title', } DEFAULT_ART_FILENAME = 'cover' diff --git a/test/test_db.py b/test/test_db.py index 22d64720b..89280c554 100644 --- a/test/test_db.py +++ b/test/test_db.py @@ -248,13 +248,33 @@ class DestinationTest(unittest.TestCase): def test_default_path_for_non_compilations(self): self.i.comp = False + self.lib.add_album([self.i]) self.lib.directory = 'one' self.lib.path_formats = {'default': 'two', 'comp': 'three'} self.assertEqual(self.lib.destination(self.i), np('one/two')) + def test_singleton_path(self): + i = item() + self.lib.directory = 'one' + self.lib.path_formats = {'default': 'two', + 'comp': 'three', + 'singleton': 'four'} + self.assertEqual(self.lib.destination(i), np('one/four')) + + def test_singleton_track_falls_back_to_default(self): + i = item() + i.comp = True + i.albumtype = 'atype' + self.lib.directory = 'one' + self.lib.path_formats = {'default': 'two', + 'comp': 'three', + 'atype': 'four'} + self.assertEqual(self.lib.destination(i), np('one/two')) + def test_comp_path(self): self.i.comp = True + self.lib.add_album([self.i]) self.lib.directory = 'one' self.lib.path_formats = {'default': 'two', 'comp': 'three'} @@ -262,6 +282,7 @@ class DestinationTest(unittest.TestCase): def test_albumtype_path(self): self.i.comp = True + self.lib.add_album([self.i]) self.i.albumtype = 'sometype' self.lib.directory = 'one' self.lib.path_formats = {'default': 'two', @@ -271,6 +292,7 @@ class DestinationTest(unittest.TestCase): def test_albumtype_path_fallback_to_comp(self): self.i.comp = True + self.lib.add_album([self.i]) self.i.albumtype = 'sometype' self.lib.directory = 'one' self.lib.path_formats = {'default': 'two',