From c8e0f0e1b8428f7481717faf943bc33c61f71096 Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Sun, 4 May 2025 14:26:07 -0600 Subject: [PATCH 1/2] Add provision for adding/removing plugin related tags. --- picard/tags/__init__.py | 10 ++++++++++ picard/tags/tagvar.py | 4 +++- picard/ui/options/plugins.py | 2 ++ test/test_tags.py | 29 +++++++++++++++++++++++++++++ 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/picard/tags/__init__.py b/picard/tags/__init__.py index c15b0ef208..f53ef5aa94 100644 --- a/picard/tags/__init__.py +++ b/picard/tags/__init__.py @@ -33,6 +33,7 @@ import re +from picard.config import get_config from picard.const.tags import ALL_TAGS @@ -126,3 +127,12 @@ def display_tag_tooltip(name): def display_tag_full_description(name): return ALL_TAGS.display_full_description(name) + + +def remove_disabled_plugin_tags(): + config = get_config() + plugins = config.setting['enabled_plugins'] + tvs = [tv for tv in ALL_TAGS if (lambda x: x.plugin_id)(tv)] + for tv in tvs: + if tv.plugin_id not in plugins: + ALL_TAGS.remove(tv) diff --git a/picard/tags/tagvar.py b/picard/tags/tagvar.py index f941af1b3a..ed9b27e400 100644 --- a/picard/tags/tagvar.py +++ b/picard/tags/tagvar.py @@ -83,7 +83,7 @@ def __init__( self, name, shortdesc=None, longdesc=None, additionaldesc=None, is_preserved=False, is_hidden=False, is_script_variable=True, is_tag=True, is_calculated=False, is_file_info=False, is_from_mb=True, is_populated_by_picard=True, is_multi_value=False, - see_also=None, related_options=None, doc_links=None + see_also=None, related_options=None, doc_links=None, plugin_id=None ): """ shortdesc: Short description (typically one or two words) in title case that is suitable @@ -106,6 +106,7 @@ def __init__( see_also: an iterable containing ids of related tags related_options: an iterable containing the related option settings (see picard/options.py) doc_links: an iterable containing links to external documentation (DocumentLink tuples) + plugin_id: the ID of the plugin providing the tag/variable (string, default: None) """ self._name = name self._shortdesc = shortdesc @@ -123,6 +124,7 @@ def __init__( self.see_also = see_also self.related_options = related_options self.doc_links = doc_links + self.plugin_id = plugin_id @property def shortdesc(self): diff --git a/picard/ui/options/plugins.py b/picard/ui/options/plugins.py index ecb70e61eb..e767f391a6 100644 --- a/picard/ui/options/plugins.py +++ b/picard/ui/options/plugins.py @@ -55,6 +55,7 @@ N_, gettext as _, ) +from picard.tags import remove_disabled_plugin_tags from picard.util import ( icontheme, open_local_path, @@ -603,6 +604,7 @@ def v2int(elem): def save(self): config = get_config() config.setting['enabled_plugins'] = self.enabled_plugins() + remove_disabled_plugin_tags() self.save_state() def refresh_details(self, item): diff --git a/test/test_tags.py b/test/test_tags.py index 094c3b83a2..b797e5f009 100644 --- a/test/test_tags.py +++ b/test/test_tags.py @@ -39,6 +39,7 @@ display_tag_tooltip, parse_comment_tag, parse_subtag, + remove_disabled_plugin_tags, script_variable_tag_names, ) from picard.tags.tagvar import ( @@ -59,6 +60,13 @@ def _translate_patch(s): return f"_({s})" +class _config_patch(): + setting = {'enabled_plugins': ['plugin_id']} + + def __init__(self): + pass + + class TagVarTest(PicardTestCase): def test_basic_properties(self): tv = TagVar('name') @@ -132,6 +140,7 @@ def setUp(self): is_file_info=True, is_hidden=True, is_script_variable=False) self.tagvar_notes2 = TagVar('notes2', shortdesc='notes2_sd', longdesc='notes2_ld', is_file_info=True, is_from_mb=False) self.tagvar_notes3 = TagVar('notes3', shortdesc='notes3_sd', longdesc='notes3_ld', is_from_mb=False) + self.tagvar_plugin = TagVar('plugin', shortdesc='plugin_sd', longdesc='plugin_ld', plugin_id='plugin_id') self.tagvar_everything = TagVar('everything', shortdesc='everything sd', longdesc='everything ld.', additionaldesc='Test additional description.', is_preserved=True, is_script_variable=False, is_tag=False, is_calculated=True, is_file_info=True, is_from_mb=False, @@ -531,3 +540,23 @@ def test_links_completeness(self): link = doc_link.link.strip() self.assertNotEqual(title, '', f"Invalid link (missing title) in '{str(tv)}' tag") self.assertNotEqual(link, '', f"Invalid link (missing URL) in '{str(tv)}' tag") + + +class TagsPluginsTest(PicardTestCase): + def setUp(self): + self.tagvar_plugin_known = TagVar('known', shortdesc='known_sd', plugin_id='plugin_id') + self.tagvar_plugin_unknown = TagVar('unknown', shortdesc='unknown_sd', plugin_id='unknown_plugin_id') + + def test_cleaning_plugin_var(self): + tagvars = TagVars( + self.tagvar_plugin_known, + self.tagvar_plugin_unknown, + ) + self.assertEqual(len(tagvars), 2) + + with mock.patch('picard.tags.get_config', return_value=_config_patch()): + with mock.patch('picard.tags.ALL_TAGS', tagvars): + remove_disabled_plugin_tags() + self.assertEqual(len(tagvars), 1) + + self.assertEqual(tagvars[0], self.tagvar_plugin_known) From 94e9b86a695f40f8472e46deafd06f7360ea9eb9 Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Mon, 5 May 2025 12:48:21 -0600 Subject: [PATCH 2/2] Filter plugin tags for disabled plugins from `TagVars.names()` method --- picard/tags/tagvar.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/picard/tags/tagvar.py b/picard/tags/tagvar.py index ed9b27e400..1a65c88527 100644 --- a/picard/tags/tagvar.py +++ b/picard/tags/tagvar.py @@ -33,6 +33,7 @@ except ImportError: markdown = None +from picard.config import get_config from picard.i18n import ( N_, gettext as _, @@ -338,6 +339,11 @@ def display_full_description(self, tagname): return self._format_display(name, content, tagdesc) def names(self, selector=None): + config = get_config() + plugins = config.setting['enabled_plugins'] if 'enabled_plugins' in config.setting else [] + for item in self._items: + if item.plugin_id and item.plugin_id not in plugins: + continue if selector is None or selector(item): yield str(item)