From 33b350a612aa80e1b2ab01e4f76cee6b76af66b1 Mon Sep 17 00:00:00 2001 From: Michael Krieger Date: Mon, 15 Sep 2025 18:50:47 -0400 Subject: [PATCH 1/5] Adds a zero_disc_if_single_disc to the zero plugin Adds a zero_disc_number_if_single_disc boolean to the zero plugin for writing to files. Adds the logic that, if disctotal is set and there is only one disc in disctotal, that the disc is not set. This keeps tags cleaner, only using disc on multi-disc albums. The disctotal is not touched, particularly as this is not usually displayed in most clients. The field is removed only for writing the tags, but the disc number is maintained in the database to avoid breaking anything that may depend on a disc number or avoid possible loops or failed logic. --- beetsplug/zero.py | 7 ++++++- docs/changelog.rst | 3 +++ docs/plugins/zero.rst | 2 ++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/beetsplug/zero.py b/beetsplug/zero.py index bce3b1a72..e65dd8286 100644 --- a/beetsplug/zero.py +++ b/beetsplug/zero.py @@ -41,6 +41,7 @@ class ZeroPlugin(BeetsPlugin): "fields": [], "keep_fields": [], "update_database": False, + "zero_disc_if_single_disc": False, } ) @@ -123,8 +124,12 @@ class ZeroPlugin(BeetsPlugin): """ fields_set = False + if "disc" in tags and self.config["zero_disc_if_single_disc"].get(bool) and item.disctotal == 1: + self._log.debug("disc: {.disc} -> None", item) + tags["disc"] = None + if not self.fields_to_progs: - self._log.warning("no fields, nothing to do") + self._log.warning("no fields list to remove") return False for field, progs in self.fields_to_progs.items(): diff --git a/docs/changelog.rst b/docs/changelog.rst index 4f32093fe..f5109a9b4 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -8,6 +8,9 @@ Unreleased ---------- New features: +* :doc:`plugins/zero`: Add new configuration option, + ``zero_disc_if_single_disc``, to allow zeroing the disc number on + write for single-disc albums. Defaults to False. Bug fixes: diff --git a/docs/plugins/zero.rst b/docs/plugins/zero.rst index 6ed9427d9..88903a389 100644 --- a/docs/plugins/zero.rst +++ b/docs/plugins/zero.rst @@ -31,6 +31,8 @@ to nullify and the conditions for nullifying them: ``keep_fields``---not both! - To conditionally filter a field, use ``field: [regexp, regexp]`` to specify regular expressions. +- Set ``zero_disc_if_single_disc`` to ``True`` to zero the disc number field + only if the album contains a disctotal count and is a single disc. - By default this plugin only affects files' tags; the beets database is left unchanged. To update the tags in the database, set the ``update_database`` option to true. From 5fc15bcfa4814418c2256e0db1b062b571ac9268 Mon Sep 17 00:00:00 2001 From: Michael Krieger Date: Mon, 15 Sep 2025 19:00:06 -0400 Subject: [PATCH 2/5] Misc formatting changes --- beetsplug/zero.py | 7 ++++--- docs/changelog.rst | 7 ++++--- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/beetsplug/zero.py b/beetsplug/zero.py index e65dd8286..c8ef9f855 100644 --- a/beetsplug/zero.py +++ b/beetsplug/zero.py @@ -124,9 +124,10 @@ class ZeroPlugin(BeetsPlugin): """ fields_set = False - if "disc" in tags and self.config["zero_disc_if_single_disc"].get(bool) and item.disctotal == 1: - self._log.debug("disc: {.disc} -> None", item) - tags["disc"] = None + if "disc" in tags and self.config["zero_disc_if_single_disc"].get(bool): + if item.disctotal == 1: + self._log.debug("disc: {.disc} -> None", item) + tags["disc"] = None if not self.fields_to_progs: self._log.warning("no fields list to remove") diff --git a/docs/changelog.rst b/docs/changelog.rst index f5109a9b4..ac3af6257 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -8,9 +8,10 @@ Unreleased ---------- New features: -* :doc:`plugins/zero`: Add new configuration option, - ``zero_disc_if_single_disc``, to allow zeroing the disc number on - write for single-disc albums. Defaults to False. + +- :doc:`plugins/zero`: Add new configuration option, + ``zero_disc_if_single_disc``, to allow zeroing the disc number on write for + single-disc albums. Defaults to False. Bug fixes: From b1c87cd98c2f7287af40fee8560234b4d0adec4e Mon Sep 17 00:00:00 2001 From: Michael Krieger Date: Tue, 16 Sep 2025 10:04:24 -0400 Subject: [PATCH 3/5] Change parameter name, add return, add tests Change the parameter name to omit_single_disc (vs previously zero_disc_if_single_disc) Add return of 'fields_set' so that, if triggered by the command line `beets zero`, it will still effect the item.write. Added tests. --- beetsplug/zero.py | 7 +++--- docs/changelog.rst | 6 ++--- docs/plugins/zero.rst | 4 ++-- test/plugins/test_zero.py | 48 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 57 insertions(+), 8 deletions(-) diff --git a/beetsplug/zero.py b/beetsplug/zero.py index c8ef9f855..c957a27d3 100644 --- a/beetsplug/zero.py +++ b/beetsplug/zero.py @@ -41,7 +41,7 @@ class ZeroPlugin(BeetsPlugin): "fields": [], "keep_fields": [], "update_database": False, - "zero_disc_if_single_disc": False, + "omit_single_disc": False, } ) @@ -124,14 +124,15 @@ class ZeroPlugin(BeetsPlugin): """ fields_set = False - if "disc" in tags and self.config["zero_disc_if_single_disc"].get(bool): + if "disc" in tags and self.config["omit_single_disc"].get(bool): if item.disctotal == 1: + fields_set = True self._log.debug("disc: {.disc} -> None", item) tags["disc"] = None if not self.fields_to_progs: self._log.warning("no fields list to remove") - return False + return fields_set for field, progs in self.fields_to_progs.items(): if field in tags: diff --git a/docs/changelog.rst b/docs/changelog.rst index ac3af6257..773c6cc67 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -9,9 +9,9 @@ Unreleased New features: -- :doc:`plugins/zero`: Add new configuration option, - ``zero_disc_if_single_disc``, to allow zeroing the disc number on write for - single-disc albums. Defaults to False. +- :doc:`plugins/zero`: Add new configuration option, ``omit_single_disc``, to + allow zeroing the disc number on write for single-disc albums. Defaults to + False. Bug fixes: diff --git a/docs/plugins/zero.rst b/docs/plugins/zero.rst index 88903a389..50b51797e 100644 --- a/docs/plugins/zero.rst +++ b/docs/plugins/zero.rst @@ -31,8 +31,8 @@ to nullify and the conditions for nullifying them: ``keep_fields``---not both! - To conditionally filter a field, use ``field: [regexp, regexp]`` to specify regular expressions. -- Set ``zero_disc_if_single_disc`` to ``True`` to zero the disc number field - only if the album contains a disctotal count and is a single disc. +- Set ``omit_single_disc`` to ``True`` to zero the disc number field only if the + album contains a disctotal count and is a single disc. - By default this plugin only affects files' tags; the beets database is left unchanged. To update the tags in the database, set the ``update_database`` option to true. diff --git a/test/plugins/test_zero.py b/test/plugins/test_zero.py index 51913c8e0..b08bf0dca 100644 --- a/test/plugins/test_zero.py +++ b/test/plugins/test_zero.py @@ -249,6 +249,54 @@ class ZeroPluginTest(PluginTestCase): assert "id" not in z.fields_to_progs + def test_omit_single_disc_with_tags_single(self): + item = self.add_item_fixture( + disctotal=1, disc=1, comments="test comment" + ) + item.write() + with self.configure_plugin( + {"omit_single_disc": True, "fields": ["comments"]} + ): + item.write() + + mf = MediaFile(syspath(item.path)) + assert mf.comments is None + assert mf.disc == 0 + + def test_omit_single_disc_with_tags_multi(self): + item = self.add_item_fixture( + disctotal=4, disc=1, comments="test comment" + ) + item.write() + with self.configure_plugin( + {"omit_single_disc": True, "fields": ["comments"]} + ): + item.write() + + mf = MediaFile(syspath(item.path)) + assert mf.comments is None + assert mf.disc == 1 + + def test_omit_single_disc_only_change_single(self): + item = self.add_item_fixture(disctotal=1, disc=1) + item.write() + + with self.configure_plugin({"omit_single_disc": True}): + item.write() + + mf = MediaFile(syspath(item.path)) + assert mf.disc == 0 + + def test_omit_single_disc_only_change_multi(self): + item = self.add_item_fixture(disctotal=4, disc=1) + item.write() + + with self.configure_plugin({"omit_single_disc": True}): + item.write() + + mf = MediaFile(syspath(item.path)) + assert mf.disc == 1 + def test_empty_query_n_response_no_changes(self): item = self.add_item_fixture( year=2016, day=13, month=3, comments="test comment" From dc133087847b676ed987a7ea8191ffe3b566af17 Mon Sep 17 00:00:00 2001 From: Michael Krieger Date: Tue, 16 Sep 2025 11:55:34 -0400 Subject: [PATCH 4/5] Remove tests. Update docs. Remove unnecessary return Remove tests. Update docs. Remove unnecessary return. --- beetsplug/zero.py | 1 - docs/plugins/zero.rst | 5 ++-- test/plugins/test_zero.py | 48 --------------------------------------- 3 files changed, 3 insertions(+), 51 deletions(-) diff --git a/beetsplug/zero.py b/beetsplug/zero.py index c957a27d3..ab1bfa5ca 100644 --- a/beetsplug/zero.py +++ b/beetsplug/zero.py @@ -132,7 +132,6 @@ class ZeroPlugin(BeetsPlugin): if not self.fields_to_progs: self._log.warning("no fields list to remove") - return fields_set for field, progs in self.fields_to_progs.items(): if field in tags: diff --git a/docs/plugins/zero.rst b/docs/plugins/zero.rst index 50b51797e..bf134e664 100644 --- a/docs/plugins/zero.rst +++ b/docs/plugins/zero.rst @@ -31,8 +31,9 @@ to nullify and the conditions for nullifying them: ``keep_fields``---not both! - To conditionally filter a field, use ``field: [regexp, regexp]`` to specify regular expressions. -- Set ``omit_single_disc`` to ``True`` to zero the disc number field only if the - album contains a disctotal count and is a single disc. +- Set ``omit_single_disc`` to ``True`` to omit writing the ``disc`` number for + albums with only a single disc (``disctotal == 1``). By default, beets will + number the disc even if the album contains only one disc in total. - By default this plugin only affects files' tags; the beets database is left unchanged. To update the tags in the database, set the ``update_database`` option to true. diff --git a/test/plugins/test_zero.py b/test/plugins/test_zero.py index b08bf0dca..51913c8e0 100644 --- a/test/plugins/test_zero.py +++ b/test/plugins/test_zero.py @@ -249,54 +249,6 @@ class ZeroPluginTest(PluginTestCase): assert "id" not in z.fields_to_progs - def test_omit_single_disc_with_tags_single(self): - item = self.add_item_fixture( - disctotal=1, disc=1, comments="test comment" - ) - item.write() - with self.configure_plugin( - {"omit_single_disc": True, "fields": ["comments"]} - ): - item.write() - - mf = MediaFile(syspath(item.path)) - assert mf.comments is None - assert mf.disc == 0 - - def test_omit_single_disc_with_tags_multi(self): - item = self.add_item_fixture( - disctotal=4, disc=1, comments="test comment" - ) - item.write() - with self.configure_plugin( - {"omit_single_disc": True, "fields": ["comments"]} - ): - item.write() - - mf = MediaFile(syspath(item.path)) - assert mf.comments is None - assert mf.disc == 1 - - def test_omit_single_disc_only_change_single(self): - item = self.add_item_fixture(disctotal=1, disc=1) - item.write() - - with self.configure_plugin({"omit_single_disc": True}): - item.write() - - mf = MediaFile(syspath(item.path)) - assert mf.disc == 0 - - def test_omit_single_disc_only_change_multi(self): - item = self.add_item_fixture(disctotal=4, disc=1) - item.write() - - with self.configure_plugin({"omit_single_disc": True}): - item.write() - - mf = MediaFile(syspath(item.path)) - assert mf.disc == 1 - def test_empty_query_n_response_no_changes(self): item = self.add_item_fixture( year=2016, day=13, month=3, comments="test comment" From df8cd23ae7979a82fdcf8d0b31a2dec8676dc43b Mon Sep 17 00:00:00 2001 From: Michael Krieger Date: Tue, 16 Sep 2025 11:57:50 -0400 Subject: [PATCH 5/5] Add back tests as they were. Add back tests as they were. --- test/plugins/test_zero.py | 48 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/test/plugins/test_zero.py b/test/plugins/test_zero.py index 51913c8e0..b08bf0dca 100644 --- a/test/plugins/test_zero.py +++ b/test/plugins/test_zero.py @@ -249,6 +249,54 @@ class ZeroPluginTest(PluginTestCase): assert "id" not in z.fields_to_progs + def test_omit_single_disc_with_tags_single(self): + item = self.add_item_fixture( + disctotal=1, disc=1, comments="test comment" + ) + item.write() + with self.configure_plugin( + {"omit_single_disc": True, "fields": ["comments"]} + ): + item.write() + + mf = MediaFile(syspath(item.path)) + assert mf.comments is None + assert mf.disc == 0 + + def test_omit_single_disc_with_tags_multi(self): + item = self.add_item_fixture( + disctotal=4, disc=1, comments="test comment" + ) + item.write() + with self.configure_plugin( + {"omit_single_disc": True, "fields": ["comments"]} + ): + item.write() + + mf = MediaFile(syspath(item.path)) + assert mf.comments is None + assert mf.disc == 1 + + def test_omit_single_disc_only_change_single(self): + item = self.add_item_fixture(disctotal=1, disc=1) + item.write() + + with self.configure_plugin({"omit_single_disc": True}): + item.write() + + mf = MediaFile(syspath(item.path)) + assert mf.disc == 0 + + def test_omit_single_disc_only_change_multi(self): + item = self.add_item_fixture(disctotal=4, disc=1) + item.write() + + with self.configure_plugin({"omit_single_disc": True}): + item.write() + + mf = MediaFile(syspath(item.path)) + assert mf.disc == 1 + def test_empty_query_n_response_no_changes(self): item = self.add_item_fixture( year=2016, day=13, month=3, comments="test comment"