Refactor according to review comments

This commit is contained in:
Nicholas Boyd Isacsson 2024-10-12 15:34:05 +02:00
parent 9bc586d7ea
commit 195644fc46
3 changed files with 37 additions and 43 deletions

View file

@ -35,7 +35,7 @@ class Substitute(BeetsPlugin):
"""Do the actual replacing.""" """Do the actual replacing."""
if text: if text:
for pattern, replacement in self.substitute_rules: 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: if subs_made > 0:
return new_text return new_text
return text return text
@ -48,7 +48,7 @@ class Substitute(BeetsPlugin):
Get the configuration, register template function and create list of Get the configuration, register template function and create list of
substitute rules. substitute rules.
""" """
super(Substitute, self).__init__() super().__init__()
self.substitute_rules = [] self.substitute_rules = []
self.template_funcs["substitute"] = self.tmpl_substitute 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: else:
pairs = self.config.as_pairs() pairs = self.config.as_pairs()

View file

@ -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 Each rule consists of a case-insensitive regular expression pattern, and a
replacement string. For example, you might use: replacement string. For example, you might use:
.. code-block:: yaml
substitute: substitute:
- .*jimi hendrix.*: Jimi Hendrix - .*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 everything before the first ``,``, `` &`` or `` and``, and use this capture
group in the output, discarding the rest of the string. group in the output, discarding the rest of the string.
.. code-block:: yaml
substitute: substitute:
- ^(.*?)(,| &| and).*: \1 - ^(.*?)(,| &| 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: To apply the substitution, you have to call the function ``%substitute{}`` in the paths section. For example:
.. code-block:: yaml
paths: paths:
default: %substitute{$albumartist}/$year - $album%aunique{}/$track - $title default: %substitute{$albumartist}/$year - $album%aunique{}/$track - $title

View file

@ -17,41 +17,42 @@
from beets.test.helper import PluginTestCase, capture_log from beets.test.helper import PluginTestCase, capture_log
from beetsplug.substitute import Substitute from beetsplug.substitute import Substitute
PLUGIN_NAME = "substitute"
class SubstitutePluginTest(PluginTestCase): class SubstitutePluginTest(PluginTestCase):
plugin = "substitute" plugin = "substitute"
preload_plugin = False 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): def test_simple_substitute(self):
with self.configure_plugin( self.run_substitute(
[ [
{"a": "b"}, {"a": "b"},
{"b": "c"}, {"b": "c"},
{"c": "d"}, {"c": "d"},
] ],
): [("a", "b"), ("b", "c"), ("c", "d")],
cases = [("a", "b"), ("b", "c"), ("c", "d")] )
for input, expected in cases:
assert Substitute().tmpl_substitute(input) == expected
def test_case_insensitivity(self): def test_case_insensitivity(self):
with self.configure_plugin([{"a": "b"}]): self.run_substitute([{"a": "b"}], [("A", "b")])
assert Substitute().tmpl_substitute("A") == "b"
def test_unmatched_input_preserved(self): def test_unmatched_input_preserved(self):
with self.configure_plugin([{"a": "b"}]): self.run_substitute([{"a": "b"}], [("c", "c")])
assert Substitute().tmpl_substitute("c") == "c"
def test_regex_to_static(self): def test_regex_to_static(self):
with self.configure_plugin([{".*jimi hendrix.*": "Jimi Hendrix"}]): self.run_substitute(
result = Substitute().tmpl_substitute("The Jimi Hendrix Experience") [{".*jimi hendrix.*": "Jimi Hendrix"}],
assert result == "Jimi Hendrix" [("The Jimi Hendrix Experience", "Jimi Hendrix")],
)
def test_regex_capture_group(self): def test_regex_capture_group(self):
with self.configure_plugin([{"^(.*?)(,| &| and).*": r"\1"}]): self.run_substitute(
cases = [ [{"^(.*?)(,| &| and).*": r"\1"}],
[
("King Creosote & Jon Hopkins", "King Creosote"), ("King Creosote & Jon Hopkins", "King Creosote"),
( (
"Michael Hurley, The Holy Modal Rounders, Jeffrey Frederick & " "Michael Hurley, The Holy Modal Rounders, Jeffrey Frederick & "
@ -59,43 +60,33 @@ class SubstitutePluginTest(PluginTestCase):
"Michael Hurley", "Michael Hurley",
), ),
("James Yorkston and the Athletes", "James Yorkston"), ("James Yorkston and the Athletes", "James Yorkston"),
] ],
for input, expected in cases: )
assert Substitute().tmpl_substitute(input) == expected
def test_partial_substitution(self): def test_partial_substitution(self):
with self.configure_plugin([{r"\.": ""}]): self.run_substitute([{r"\.": ""}], [("U.N.P.O.C.", "UNPOC")])
cases = [
("U.N.P.O.C.", "UNPOC"),
]
for input, expected in cases:
assert Substitute().tmpl_substitute(input) == expected
def test_break_on_first_match(self): def test_break_on_first_match(self):
with self.configure_plugin( self.run_substitute(
[ [
{"a": "b"}, {"a": "b"},
{"[ab]": "c"}, {"[ab]": "c"},
] ],
): [
cases = [
("a", "b"), ("a", "b"),
("b", "c"), ("b", "c"),
] ],
for input, expected in cases: )
assert Substitute().tmpl_substitute(input) == expected
def test_deprecated_config(self): def test_deprecated_config(self):
with self.configure_plugin( self.run_substitute(
{ {
"a": "b", "a": "b",
"b": "c", "b": "c",
"c": "d", "c": "d",
} },
): [("a", "b"), ("b", "c"), ("c", "d")],
cases = [("a", "b"), ("b", "c"), ("c", "d")] )
for input, expected in cases:
assert Substitute().tmpl_substitute(input) == expected
def test_deprecated_config_warning(self): def test_deprecated_config_warning(self):
with capture_log() as logs: with capture_log() as logs: