diff --git a/beets/library.py b/beets/library.py index 981563974..b4a8680d8 100644 --- a/beets/library.py +++ b/beets/library.py @@ -1355,9 +1355,12 @@ class Album(LibModel): """ # Get modified track fields. track_updates = {} - for key in self.item_keys: - if key in self._dirty: + track_deletes = set() + for key in self._dirty: + if key in self.item_keys: track_updates[key] = self[key] + elif key not in self: + track_deletes.add(key); with self._db.transaction(): super().store(fields) @@ -1366,6 +1369,12 @@ class Album(LibModel): for key, value in track_updates.items(): item[key] = value item.store() + if track_deletes: + for item in self.items(): + for key in track_deletes: + if key in item: + del item[key] + item.store() def try_sync(self, write, move): """Synchronize the album and its items with the database. diff --git a/docs/changelog.rst b/docs/changelog.rst index 66802d203..f39282633 100755 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -133,6 +133,8 @@ Bug fixes: * :doc:`/plugins/fromfilename`: Fix failed detection of filename patterns. :bug:`4561` :bug:`4600` +* Fix issue where deletion of flexible fields on an album doesn't cascade to items + :bug:`4662` For packagers: diff --git a/test/test_library.py b/test/test_library.py index 5e57afb17..e94bffa6a 100644 --- a/test/test_library.py +++ b/test/test_library.py @@ -77,6 +77,19 @@ class StoreTest(_common.LibTestCase): self.i.store() self.assertTrue('composer' not in self.i._dirty) + def test_store_album_cascades_flex_deletes(self): + album = _common.album() + album.flex1="Flex-1" + self.lib.add(album) + item = _common.item() + item.album_id = album.id + item.flex1="Flex-1" + self.lib.add(item) + del album.flex1 + album.store() + self.assertNotIn('flex1', album) + self.assertNotIn('flex1', album.items()[0]) + class AddTest(_common.TestCase): def setUp(self):