Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion beets/dbcore/db.py
Original file line number Diff line number Diff line change
Expand Up @@ -599,7 +599,7 @@ def store(self, fields: Iterable[str] | 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])
Expand Down
2 changes: 2 additions & 0 deletions docs/changelog.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ Bug fixes
example a multi-disc album whose cover lives in the album root rather than a
per-disc directory); the missing art is skipped instead. :bug:`4692`
- :doc:`plugins/tidal`: Normalize Tidal album types to lowercase.
- ``beet update`` no longer crashes when a plugin-added media field is stored as
a flexible attribute. :bug:`5580`

..
For plugin developers
Expand Down
9 changes: 9 additions & 0 deletions test/test_dbcore.py
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,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"
Expand Down
25 changes: 25 additions & 0 deletions test/ui/commands/test_update.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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"
Expand Down
Loading