diff --git a/beets/dbcore/db.py b/beets/dbcore/db.py index e66f4548bf..a16ad582e6 100755 --- a/beets/dbcore/db.py +++ b/beets/dbcore/db.py @@ -590,7 +590,7 @@ def store(self, fields: Iterable[str] | None = None) -> None: assignments = [] subvars: list[SQLiteType] = [] for key in fields: - if key != "id" and key in self._dirty: + if key != "id" and key in self._fields and key in self._dirty: self._dirty.remove(key) assignments.append(f"{key}=?") value = self._type(key).to_sql(self[key]) diff --git a/docs/changelog.rst b/docs/changelog.rst index 30fbfa3e60..7fec5df5c9 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -114,6 +114,8 @@ Bug fixes valid date/time string" error instead of crashing with an uncaught ``KeyError``. A ``|`` was being accepted as a relative-date unit due to a regular expression character-class typo. +- ``beet update`` no longer crashes when a plugin-added media field is stored as + a flexible attribute. :bug:`5580` .. For plugin developers diff --git a/test/dbcore/test_db.py b/test/dbcore/test_db.py index 829919847a..353a30ae3b 100644 --- a/test/dbcore/test_db.py +++ b/test/dbcore/test_db.py @@ -281,6 +281,15 @@ def test_store_and_retrieve_flexattr(self): other_model = self.db._get(ModelFixture1, model.id) assert other_model.foo == "bar" + def test_store_flexattr_in_fields(self): + model = ModelFixture1() + model.add(self.db) + model.foo = "bar" + model.store(fields=["foo"]) + + other_model = self.db._get(ModelFixture1, model.id) + assert other_model.foo == "bar" + def test_delete_flexattr(self): model = ModelFixture1() model["foo"] = "bar" diff --git a/test/ui/commands/test_update.py b/test/ui/commands/test_update.py index 1b7d368346..aa98508da2 100644 --- a/test/ui/commands/test_update.py +++ b/test/ui/commands/test_update.py @@ -1,8 +1,10 @@ import os +import mediafile from mediafile import MediaFile from beets import library +from beets.plugins import BeetsPlugin from beets.test import _common from beets.test.helper import BeetsTestCase, IOMixin from beets.ui.commands.update import update_items @@ -84,6 +86,29 @@ def test_modified_metadata_detected(self): item = self.lib.items().get() assert item.title == "differentTitle" + def test_modified_plugin_media_field_detected(self): + plugin = BeetsPlugin() + plugin.add_media_field( + "customtag", + mediafile.MediaField( + mediafile.MP3DescStorageStyle("customtag"), + mediafile.StorageStyle("customtag"), + ), + ) + + try: + mf = MediaFile(syspath(self.i.path)) + mf.customtag = "F#" + mf.save() + + self._update() + + item = self.lib.get_item(self.i.id) + assert item["customtag"] == "F#" + finally: + delattr(mediafile.MediaFile, "customtag") + library.Item._media_fields.remove("customtag") + def test_modified_metadata_moved(self): mf = MediaFile(syspath(self.i.path)) mf.title = "differentTitle"