Skip to content

Update mediafields regression #5580

Open
@pvliesdonk

Description

Problem

I created a plugin to read/write additional tags from a file as per https://beets.readthedocs.io/en/stable/dev/plugins.html#extend-mediafile, e.g.

class FooPlugin(BeetsPlugin):
    def __init__(self):
        field = mediafile.MediaField(
            mediafile.MP3DescStorageStyle(u'foo'),
            mediafile.StorageStyle(u'foo')
        )
        self.add_media_field('foo', field)

Executing an update as beet up fails with the following traceback:

Traceback (most recent call last):
  File "/home/peter/bin/beet", line 8, in <module>
    sys.exit(main())
             ^^^^^^
  File "/mnt/code/beets/beets/ui/__init__.py", line 1870, in main
    _raw_main(args)
  File "/mnt/code/beets/beets/ui/__init__.py", line 1849, in _raw_main
    subcommand.func(lib, suboptions, subargs)
  File "/mnt/code/beets/beets/ui/commands.py", line 1745, in update_func
    update_items(
  File "/mnt/code/beets/beets/ui/commands.py", line 1697, in update_items
    item.store(fields=item_fields)
  File "/mnt/code/beets/beets/library.py", line 396, in store
    super().store(fields)
  File "/mnt/code/beets/beets/dbcore/db.py", line 608, in store
    tx.mutate(query, subvars)
  File "/mnt/code/beets/beets/dbcore/db.py", line 985, in mutate
    cursor = self.db._connection().execute(statement, subvals)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
sqlite3.OperationalError: no such column: foo

Digging down into this problem leads me to the following commit: acff509

-        item_fields = fields or library.Item._fields.keys()
+        if fields is None:
+            # no fields were provided, update all media fields
+            item_fields = fields or library.Item._media_fields

The commit makes the assumption that if no fields are given, all fields in library.Item._media_fields should be updated.
Fields in library.Item._media_fields can be both fixed or flex.

This escalates a bit later in the same function where item.store(fields=item_fields) is called.
Its implementation

def store(self, fields: Iterable[str] | None = None):

seems to assume that field only contains fixed fields and tries to update a flex as if it is a fixed.

Solution

Partially rolling back commit acff509 by assuming all fields from library.Item._fields.keys() must be included solves the problem. I'll create PR for that.

However, I think the real issue is in the dbcore.db.Model.store() implementation

Setup

  • OS: Manjaro Linux
  • Python version: 3.12.7
  • beets version: v2.2.0
  • Turning off plugins made problem go away (yes/no): no

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions