From 46a3bde5b51fe040ae1d06494b1d20d53fbd35b0 Mon Sep 17 00:00:00 2001 From: Adrian Sampson Date: Fri, 16 Dec 2011 12:08:39 -0800 Subject: [PATCH] fix empty function arguments Previously, an empty argument was treated as "not an argument at all". Now, every function call always has at least one argument -- i.e., %foo{} is a function call whose only argument is "" -- and %foo{,bar} is valid syntax. --- beets/util/functemplate.py | 7 ++----- test/test_db.py | 4 ++-- test/test_template.py | 10 +++++++--- 3 files changed, 11 insertions(+), 10 deletions(-) diff --git a/beets/util/functemplate.py b/beets/util/functemplate.py index 4f1fe595f..1c2384a4c 100644 --- a/beets/util/functemplate.py +++ b/beets/util/functemplate.py @@ -298,13 +298,9 @@ class Parser(object): # Try to parse a subexpression in a subparser. expressions = [] - while self.pos < len(self.string) and \ - self.string[self.pos] != GROUP_CLOSE: + while self.pos < len(self.string): subparser = Parser(self.string[self.pos:]) subparser.parse_expression() - if subparser.pos == 0: - # No expression could be parsed. - break # Extract and advance past the parsed expression. expressions.append(Expression(subparser.parts)) @@ -316,6 +312,7 @@ class Parser(object): break # Only other way to terminate an expression is with ,. + # Continue to the next argument. assert self.string[self.pos] == ARG_SEP self.pos += 1 diff --git a/test/test_db.py b/test/test_db.py index 659477dd2..863dee49c 100644 --- a/test/test_db.py +++ b/test/test_db.py @@ -398,8 +398,8 @@ class DestinationFunctionTest(unittest.TestCase): self._assert_dest('/base/tle') def test_if_false(self): - self._setf(u'%if{,foo}') - self._assert_dest('/base/') + self._setf(u'x%if{,foo}') + self._assert_dest('/base/x') def test_if_true(self): self._setf(u'%if{bar,foo}') diff --git a/test/test_template.py b/test/test_template.py index 29d5d384f..f69af0b1e 100644 --- a/test/test_template.py +++ b/test/test_template.py @@ -147,10 +147,11 @@ class ParseTest(unittest.TestCase): self.assertEqual(list(_normparse(u'foo %bar{bar,bar baz')), [u'foo %bar{bar,bar baz']) - def test_call_no_args(self): + def test_call_empty_arg(self): parts = list(_normparse(u'%foo{}')) self.assertEqual(len(parts), 1) - self._assert_call(parts[0], u"foo", 0) + self._assert_call(parts[0], u"foo", 1) + self.assertEqual(list(_normexpr(parts[0].args[0])), []) def test_call_single_arg(self): parts = list(_normparse(u'%foo{bar}')) @@ -192,7 +193,7 @@ class ParseTest(unittest.TestCase): self._assert_call(parts[0], u"foo", 2) arg_parts = list(_normexpr(parts[0].args[0])) self.assertEqual(len(arg_parts), 1) - self._assert_call(arg_parts[0], u"bar", 0) + self._assert_call(arg_parts[0], u"bar", 1) self.assertEqual(list(_normexpr(parts[0].args[1])), [u"baz"]) def test_nested_call_with_argument(self): @@ -253,6 +254,9 @@ class EvalTest(unittest.TestCase): def test_not_subtitute_func_with_no_args(self): self.assertEqual(self._eval(u"%lower"), u"%lower") + def test_function_call_with_empty_arg(self): + self.assertEqual(self._eval(u"%len{}"), u"0") + def suite(): return unittest.TestLoader().loadTestsFromName(__name__)