diff --git a/beetsplug/substitute.py b/beetsplug/substitute.py index 84eca9de1..d6476ae2f 100644 --- a/beetsplug/substitute.py +++ b/beetsplug/substitute.py @@ -35,7 +35,7 @@ class Substitute(BeetsPlugin): """Do the actual replacing.""" if text: for pattern, replacement in self.substitute_rules: - new_text, subs_made = re.subn(pattern, replacement, text) + new_text, subs_made = pattern.subn(replacement, text) if subs_made > 0: return new_text return text @@ -48,7 +48,7 @@ class Substitute(BeetsPlugin): Get the configuration, register template function and create list of substitute rules. """ - super(Substitute, self).__init__() + super().__init__() self.substitute_rules = [] self.template_funcs["substitute"] = self.tmpl_substitute @@ -70,7 +70,7 @@ class Substitute(BeetsPlugin): """ ) ) - pairs = [(key, view.as_str()) for key, view in self.config.items()] + pairs = self.config.flatten().items() else: pairs = self.config.as_pairs() diff --git a/docs/plugins/substitute.rst b/docs/plugins/substitute.rst index acd35226f..1ea4f8f55 100644 --- a/docs/plugins/substitute.rst +++ b/docs/plugins/substitute.rst @@ -13,6 +13,7 @@ Enable the ``substitute`` plugin (see :ref:`using-plugins`), then make a ``subst Each rule consists of a case-insensitive regular expression pattern, and a replacement string. For example, you might use: +.. code-block:: yaml substitute: - .*jimi hendrix.*: Jimi Hendrix @@ -22,6 +23,7 @@ multiple artists into the directory of the first artist. We can thus capture everything before the first ``,``, `` &`` or `` and``, and use this capture group in the output, discarding the rest of the string. +.. code-block:: yaml substitute: - ^(.*?)(,| &| and).*: \1 @@ -34,5 +36,6 @@ This would handle all the below cases in a single rule: To apply the substitution, you have to call the function ``%substitute{}`` in the paths section. For example: +.. code-block:: yaml paths: - default: %substitute{$albumartist}/$year - $album%aunique{}/$track - $title \ No newline at end of file + default: %substitute{$albumartist}/$year - $album%aunique{}/$track - $title diff --git a/test/plugins/test_substitute.py b/test/plugins/test_substitute.py index 336edda9e..d193400d6 100644 --- a/test/plugins/test_substitute.py +++ b/test/plugins/test_substitute.py @@ -17,41 +17,42 @@ from beets.test.helper import PluginTestCase, capture_log from beetsplug.substitute import Substitute -PLUGIN_NAME = "substitute" - class SubstitutePluginTest(PluginTestCase): plugin = "substitute" preload_plugin = False + def run_substitute(self, config, cases): + with self.configure_plugin(config): + for input, expected in cases: + assert Substitute().tmpl_substitute(input) == expected + def test_simple_substitute(self): - with self.configure_plugin( + self.run_substitute( [ {"a": "b"}, {"b": "c"}, {"c": "d"}, - ] - ): - cases = [("a", "b"), ("b", "c"), ("c", "d")] - for input, expected in cases: - assert Substitute().tmpl_substitute(input) == expected + ], + [("a", "b"), ("b", "c"), ("c", "d")], + ) def test_case_insensitivity(self): - with self.configure_plugin([{"a": "b"}]): - assert Substitute().tmpl_substitute("A") == "b" + self.run_substitute([{"a": "b"}], [("A", "b")]) def test_unmatched_input_preserved(self): - with self.configure_plugin([{"a": "b"}]): - assert Substitute().tmpl_substitute("c") == "c" + self.run_substitute([{"a": "b"}], [("c", "c")]) def test_regex_to_static(self): - with self.configure_plugin([{".*jimi hendrix.*": "Jimi Hendrix"}]): - result = Substitute().tmpl_substitute("The Jimi Hendrix Experience") - assert result == "Jimi Hendrix" + self.run_substitute( + [{".*jimi hendrix.*": "Jimi Hendrix"}], + [("The Jimi Hendrix Experience", "Jimi Hendrix")], + ) def test_regex_capture_group(self): - with self.configure_plugin([{"^(.*?)(,| &| and).*": r"\1"}]): - cases = [ + self.run_substitute( + [{"^(.*?)(,| &| and).*": r"\1"}], + [ ("King Creosote & Jon Hopkins", "King Creosote"), ( "Michael Hurley, The Holy Modal Rounders, Jeffrey Frederick & " @@ -59,43 +60,33 @@ class SubstitutePluginTest(PluginTestCase): "Michael Hurley", ), ("James Yorkston and the Athletes", "James Yorkston"), - ] - for input, expected in cases: - assert Substitute().tmpl_substitute(input) == expected + ], + ) def test_partial_substitution(self): - with self.configure_plugin([{r"\.": ""}]): - cases = [ - ("U.N.P.O.C.", "UNPOC"), - ] - for input, expected in cases: - assert Substitute().tmpl_substitute(input) == expected + self.run_substitute([{r"\.": ""}], [("U.N.P.O.C.", "UNPOC")]) def test_break_on_first_match(self): - with self.configure_plugin( + self.run_substitute( [ {"a": "b"}, {"[ab]": "c"}, - ] - ): - cases = [ + ], + [ ("a", "b"), ("b", "c"), - ] - for input, expected in cases: - assert Substitute().tmpl_substitute(input) == expected + ], + ) def test_deprecated_config(self): - with self.configure_plugin( + self.run_substitute( { "a": "b", "b": "c", "c": "d", - } - ): - cases = [("a", "b"), ("b", "c"), ("c", "d")] - for input, expected in cases: - assert Substitute().tmpl_substitute(input) == expected + }, + [("a", "b"), ("b", "c"), ("c", "d")], + ) def test_deprecated_config_warning(self): with capture_log() as logs: