Skip to content

Convert flexible field values to SQL before storing them #5833

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from

Conversation

Maxr1998
Copy link
Contributor

@Maxr1998 Maxr1998 commented Jun 22, 2025

Description

This is required to support list values in flexible fields.
See #5698 for more details.

To Do

  • Changelog. (Add an entry to docs/changelog.rst to the bottom of one of the lists near the top of the document.)
  • Tests. (Very much encouraged but not strictly required.)

@Copilot Copilot AI review requested due to automatic review settings June 22, 2025 14:57
Copy link

Thank you for the PR! The changelog has not been updated, so here is a friendly reminder to check if you need to add an entry.

Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR adds conversion of flexible field values to their SQL representation before inserting them into the database, enabling support for multivalued flexible fields.

  • Applies to_sql on each flexible field value prior to storage.
  • Removes keys from the dirty set as before, then converts and inserts the SQL value.
  • (To be added) Changelog and tests for the new behavior.
Comments suppressed due to low confidence (2)

beets/dbcore/db.py:607

  • [nitpick] Overwriting the original value variable may reduce readability; consider assigning the converted value to a new variable (e.g., sql_value) and using that in the mutate call.
                    value = self._type(key).to_sql(value)

beets/dbcore/db.py:607

  • Add tests to cover the new to_sql conversion path for flexible fields, verifying that multivalued and edge-case values produce the expected SQL representations.
                    value = self._type(key).to_sql(value)

@Maxr1998
Copy link
Contributor Author

I'm having a hard time writing tests for this. It looks like my types aren't getting registered:

diff --git a/test/test_plugins.py b/test/test_plugins.py
--- a/test/test_plugins.py	(revision 40d83b5b32b313d8dd7a13a1ed989b3760fdacdd)
+++ b/test/test_plugins.py	(date 1751198533085)
@@ -94,6 +94,17 @@
         out = self.run_with_output("ls", "rating:3..5")
         assert "aaa" not in out
 
+    def test_multi_value_flex_field_type(self):
+        class MultiValuePlugin(plugins.BeetsPlugin):
+            item_types = {"multi_value": types.MULTI_VALUE_DSV}
+
+        self.register_plugin(MultiValuePlugin)
+        assert plugins.types(Item) is not None
+
+        item = Item(path="apath", artist="aaa")
+        item.multi_value = ["one", "two", "three"]
+        item.add(self.lib) # throws an error
+
 
 class ItemWriteTest(PluginLoaderTestCase):
     def setUp(self):

Any ideas?

@Maxr1998
Copy link
Contributor Author

@snejus, did you have a chance to look into this already?

@snejus
Copy link
Member

snejus commented Jul 15, 2025

@snejus, did you have a chance to look into this already?

Yes, I finally have! You've uncovered a fundamental issue with how we register types and queries provided by plugins, which makes it nearly impossible to test properly.

I've just opened a PR with a fix. You can try to rebase on top of it and try testing again :)

@Maxr1998
Copy link
Contributor Author

Thank you so much! Seems to work now. I'll finish my tests and push everything when it's done.

snejus added a commit that referenced this pull request Jul 16, 2025
## Fix dynamic plugin type and query registration

This PR refactors the plugin system to properly handle dynamic type and
query registration by converting static class attributes to cached class
properties.

**Problem**: Plugin types and queries were stored as mutable class
attributes that were manually updated during plugin loading/unloading.
This caused issues where:
- Plugin types weren't properly registered in test environments
- Shared mutable state between test runs caused inconsistent behavior  
- Manual cleanup was error-prone and incomplete

See #5833 and specifically
#5833 (comment) for
the context.

**Solution**: 
- Convert `_types` and `_queries` from static dictionaries to
`@cached_classproperty` decorators
- Types and queries are now dynamically computed from loaded plugins
when accessed
- Eliminates manual mutation of class attributes during plugin loading
- Properly clears cached properties when plugins are loaded/unloaded
- Ensures plugin types are available immediately after registration

**Key Changes**:
- `Model._types` and `LibModel._queries` now use `@cached_classproperty`
- Removed manual `_types.update()` calls in plugin loading code
- Added proper cache clearing in test infrastructure
- Plugin types are now inherited through the class hierarchy correctly

This fixes the developer's issue where `item_types` weren't being
registered properly in tests - the new dynamic property approach ensures
plugin types are available as soon as plugins are loaded.
@snejus
Copy link
Member

snejus commented Jul 16, 2025

@Maxr1998 it's been merged into master, so feel free to rebase and add your test 🎉

Maxr1998 added 2 commits July 16, 2025 21:41
This is required to support multivalued fields as flexible fields.
@Maxr1998 Maxr1998 force-pushed the multivalued-flexible-fields branch from 40d83b5 to 21d03a7 Compare July 16, 2025 19:42
@Maxr1998
Copy link
Contributor Author

@snejus thank you so much for fixing it! Just rebased again and pushed my test.

Copy link

codecov bot commented Jul 16, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 63.73%. Comparing base (bde5de4) to head (8db661b).

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Maxr1998 Maxr1998 force-pushed the multivalued-flexible-fields branch from 21d03a7 to 8db661b Compare July 16, 2025 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants