From 6604d38c606934d970604aaf306ffa078da24fed Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Sat, 27 Mar 2021 11:35:07 -0600 Subject: [PATCH 1/4] Add function to remove duplicate entries from multi-value variable --- picard/script/functions.py | 26 ++++++++++++++++++++++++++ test/test_script.py | 24 ++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/picard/script/functions.py b/picard/script/functions.py index c6004810c..6787429f6 100644 --- a/picard/script/functions.py +++ b/picard/script/functions.py @@ -1296,3 +1296,29 @@ Result: C; B; A def func_reversemulti(parser, multi, separator=MULTI_VALUED_JOINER): multi_value = MultiValue(parser, multi, separator) return multi_value.separator.join(reversed(multi_value)) + + +@script_function(eval_args=False, documentation=N_( + """`$uniquemulti(name,case_sensitive="",separator="; ")` + +Returns a copy of the multi-value tag `name` with no duplicate elements. + By default, a case-insensitive comparison of the elements is performed. + +Example 1: + + $uniquemulti(a; A; B; b; cd; Cd; cD; CD; a; A; b) + +Result: A; b; CD + +Example 2: + + $uniquemulti(a; A; B; b; a; b; A; B, cd,True) + +Result: a; A; B; b; cd +""" +)) +def func_uniquemulti(parser, multi, case_sensitive="", separator=MULTI_VALUED_JOINER): + multi_value = MultiValue(parser, multi, separator) + if not case_sensitive: + multi_value._multi = list({v.lower(): v for v in multi_value}.values()) + return multi_value.separator.join(sorted(list(set(multi_value)))) diff --git a/test/test_script.py b/test/test_script.py index a719c1f0f..a1869453a 100644 --- a/test/test_script.py +++ b/test/test_script.py @@ -1494,3 +1494,27 @@ class ScriptParserTest(PicardTestCase): self.parser.eval("$reversemulti()") with self.assertRaisesRegex(ScriptError, areg): self.parser.eval("$reversemulti(B:AB; D:C; E:D; A:A; C:X,:,extra)") + + def test_cmd_uniquemulti(self): + context = Metadata() + context["foo"] = ['a', 'A', 'B', 'b', 'cd', 'Cd', 'cD', 'CD', 'a', 'A', 'b'] + context["bar"] = "a; A; B; b; cd; Cd; cD; CD; a; A; b" + # Tests with context + self.assertScriptResultEquals("$uniquemulti(%foo%)", "A; CD; b", context) + self.assertScriptResultEquals("$uniquemulti(%bar%)", "a; A; B; b; cd; Cd; cD; CD; a; A; b", context) + # Tests with static inputs + self.assertScriptResultEquals("$uniquemulti(a; A; B; b; cd; Cd; cD; CD; a; A; b)", "A; CD; b", context) + # Tests with separator override + self.assertScriptResultEquals("$uniquemulti(a: A: B: b: cd: Cd: cD: CD: a: A: b,,: )", "A: CD: b", context) + # Tests with case-sensitive comparison + self.assertScriptResultEquals("$uniquemulti(%foo%,1)", "A; B; CD; Cd; a; b; cD; cd", context) + # Tests with missing inputs + self.assertScriptResultEquals("$uniquemulti(,)", "", context) + self.assertScriptResultEquals("$uniquemulti(,,)", "", context) + self.assertScriptResultEquals("$uniquemulti(,:)", "", context) + # Tests with invalid number of arguments + areg = r"^\d+:\d+:\$uniquemulti: Wrong number of arguments for \$uniquemulti: Expected between 1 and 3, " + with self.assertRaisesRegex(ScriptError, areg): + self.parser.eval("$uniquemulti()") + with self.assertRaisesRegex(ScriptError, areg): + self.parser.eval("$uniquemulti(B:AB; D:C; E:D; A:A; C:X,1,:,extra)") From fb0a0147b5e7c3fc78350e610240ff2408dae2df Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Sat, 27 Mar 2021 11:51:49 -0600 Subject: [PATCH 2/4] Fix example output order to match sorted output --- picard/script/functions.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/picard/script/functions.py b/picard/script/functions.py index 6787429f6..57d629371 100644 --- a/picard/script/functions.py +++ b/picard/script/functions.py @@ -1308,13 +1308,13 @@ Example 1: $uniquemulti(a; A; B; b; cd; Cd; cD; CD; a; A; b) -Result: A; b; CD +Result: A; CD; b Example 2: $uniquemulti(a; A; B; b; a; b; A; B, cd,True) -Result: a; A; B; b; cd +Result: A; B; a; b; cd """ )) def func_uniquemulti(parser, multi, case_sensitive="", separator=MULTI_VALUED_JOINER): From d0335e71a8b2795832b7ead1372c3799442dda66 Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Sun, 28 Mar 2021 11:47:44 -0600 Subject: [PATCH 3/4] Clean up sorted() parameter. Change name to $unique() --- picard/script/functions.py | 10 +++++----- test/test_script.py | 24 ++++++++++++------------ 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/picard/script/functions.py b/picard/script/functions.py index 57d629371..c1642c1b7 100644 --- a/picard/script/functions.py +++ b/picard/script/functions.py @@ -1299,26 +1299,26 @@ def func_reversemulti(parser, multi, separator=MULTI_VALUED_JOINER): @script_function(eval_args=False, documentation=N_( - """`$uniquemulti(name,case_sensitive="",separator="; ")` + """`$unique(name,case_sensitive="",separator="; ")` Returns a copy of the multi-value tag `name` with no duplicate elements. By default, a case-insensitive comparison of the elements is performed. Example 1: - $uniquemulti(a; A; B; b; cd; Cd; cD; CD; a; A; b) + $unique(a; A; B; b; cd; Cd; cD; CD; a; A; b) Result: A; CD; b Example 2: - $uniquemulti(a; A; B; b; a; b; A; B, cd,True) + $unique(a; A; B; b; a; b; A; B, cd,True) Result: A; B; a; b; cd """ )) -def func_uniquemulti(parser, multi, case_sensitive="", separator=MULTI_VALUED_JOINER): +def func_unique(parser, multi, case_sensitive="", separator=MULTI_VALUED_JOINER): multi_value = MultiValue(parser, multi, separator) if not case_sensitive: multi_value._multi = list({v.lower(): v for v in multi_value}.values()) - return multi_value.separator.join(sorted(list(set(multi_value)))) + return multi_value.separator.join(sorted(set(multi_value))) diff --git a/test/test_script.py b/test/test_script.py index a1869453a..6265397e4 100644 --- a/test/test_script.py +++ b/test/test_script.py @@ -1495,26 +1495,26 @@ class ScriptParserTest(PicardTestCase): with self.assertRaisesRegex(ScriptError, areg): self.parser.eval("$reversemulti(B:AB; D:C; E:D; A:A; C:X,:,extra)") - def test_cmd_uniquemulti(self): + def test_cmd_unique(self): context = Metadata() context["foo"] = ['a', 'A', 'B', 'b', 'cd', 'Cd', 'cD', 'CD', 'a', 'A', 'b'] context["bar"] = "a; A; B; b; cd; Cd; cD; CD; a; A; b" # Tests with context - self.assertScriptResultEquals("$uniquemulti(%foo%)", "A; CD; b", context) - self.assertScriptResultEquals("$uniquemulti(%bar%)", "a; A; B; b; cd; Cd; cD; CD; a; A; b", context) + self.assertScriptResultEquals("$unique(%foo%)", "A; CD; b", context) + self.assertScriptResultEquals("$unique(%bar%)", "a; A; B; b; cd; Cd; cD; CD; a; A; b", context) # Tests with static inputs - self.assertScriptResultEquals("$uniquemulti(a; A; B; b; cd; Cd; cD; CD; a; A; b)", "A; CD; b", context) + self.assertScriptResultEquals("$unique(a; A; B; b; cd; Cd; cD; CD; a; A; b)", "A; CD; b", context) # Tests with separator override - self.assertScriptResultEquals("$uniquemulti(a: A: B: b: cd: Cd: cD: CD: a: A: b,,: )", "A: CD: b", context) + self.assertScriptResultEquals("$unique(a: A: B: b: cd: Cd: cD: CD: a: A: b,,: )", "A: CD: b", context) # Tests with case-sensitive comparison - self.assertScriptResultEquals("$uniquemulti(%foo%,1)", "A; B; CD; Cd; a; b; cD; cd", context) + self.assertScriptResultEquals("$unique(%foo%,1)", "A; B; CD; Cd; a; b; cD; cd", context) # Tests with missing inputs - self.assertScriptResultEquals("$uniquemulti(,)", "", context) - self.assertScriptResultEquals("$uniquemulti(,,)", "", context) - self.assertScriptResultEquals("$uniquemulti(,:)", "", context) + self.assertScriptResultEquals("$unique(,)", "", context) + self.assertScriptResultEquals("$unique(,,)", "", context) + self.assertScriptResultEquals("$unique(,:)", "", context) # Tests with invalid number of arguments - areg = r"^\d+:\d+:\$uniquemulti: Wrong number of arguments for \$uniquemulti: Expected between 1 and 3, " + areg = r"^\d+:\d+:\$unique: Wrong number of arguments for \$unique: Expected between 1 and 3, " with self.assertRaisesRegex(ScriptError, areg): - self.parser.eval("$uniquemulti()") + self.parser.eval("$unique()") with self.assertRaisesRegex(ScriptError, areg): - self.parser.eval("$uniquemulti(B:AB; D:C; E:D; A:A; C:X,1,:,extra)") + self.parser.eval("$unique(B:AB; D:C; E:D; A:A; C:X,1,:,extra)") From 33b4d1dec2b7c7fcd21a9c80bea1de8e2f7b4f4c Mon Sep 17 00:00:00 2001 From: Bob Swift Date: Sun, 28 Mar 2021 12:47:53 -0600 Subject: [PATCH 4/4] Correct examples --- picard/script/functions.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/picard/script/functions.py b/picard/script/functions.py index c1642c1b7..d648b80bb 100644 --- a/picard/script/functions.py +++ b/picard/script/functions.py @@ -1306,13 +1306,15 @@ Returns a copy of the multi-value tag `name` with no duplicate elements. Example 1: - $unique(a; A; B; b; cd; Cd; cD; CD; a; A; b) + $setmulti(foo,a; A; B; b; cd; Cd; cD; CD; a; A; b) + $unique(%foo%) Result: A; CD; b Example 2: - $unique(a; A; B; b; a; b; A; B, cd,True) + $setmulti(foo,a; A; B; b; a; b; A; B, cd) + $unique(%foo%,True) Result: A; B; a; b; cd """