diff --git a/picard/script.py b/picard/script.py index 254e540e5..139ce688e 100644 --- a/picard/script.py +++ b/picard/script.py @@ -92,18 +92,23 @@ class ScriptFunction(object): try: argnum_bound = parser.functions[name].argcount argcount = len(args) - if argnum_bound and not (argnum_bound.lower <= argcount - and (argnum_bound.upper is None - or argcount <= argnum_bound.upper)): - raise ScriptError( - "Wrong number of arguments for $%s: Expected %s, got %i at position %i, line %i" - % (name, - str(argnum_bound.lower) - if argnum_bound.upper is None - else "%i - %i" % (argnum_bound.lower, argnum_bound.upper), - argcount, - parser._x, - parser._y)) + if argnum_bound: + too_few_args = argcount < argnum_bound.lower + if argnum_bound.upper is not None: + if argnum_bound.lower == argnum_bound.upper: + expected = "exactly %i" % argnum_bound.lower + else: + expected = "between %i and %i" % (argnum_bound.lower, argnum_bound.upper) + too_many_args = argcount > argnum_bound.upper + else: + expected = "at least %i" % argnum_bound.lower + too_many_args = False + + if too_few_args or too_many_args: + raise ScriptError( + "Wrong number of arguments for $%s: Expected %s, got %i at position %i, line %i" + % (name, expected, argcount, parser._x, parser._y) + ) except KeyError: raise ScriptUnknownFunction("Unknown function '%s'" % name) diff --git a/test/test_script.py b/test/test_script.py index d3eddd5d8..e982fca51 100644 --- a/test/test_script.py +++ b/test/test_script.py @@ -390,6 +390,45 @@ class ScriptParserTest(PicardTestCase): except ScriptError: self.fail("Function noargs raised ScriptError unexpectedly.") + def test_cmd_with_wrong_argcount_or(self): + # $or() requires at least 2 arguments + with self.assertRaises(ScriptError): + self.parser.eval('$or(0)') + try: + self.parser.eval('$or(0,1)') + except ScriptError as why: + self.fail("Function raised ScriptError: %s" % why) + try: + self.parser.eval('$or(0,1,1,1,1)') + except ScriptError as why: + self.fail("Function raised ScriptError: %s" % why) + + def test_cmd_with_wrong_argcount_eq(self): + # $eq() requires exactly 2 arguments + with self.assertRaises(ScriptError): + self.parser.eval('$eq(0)') + with self.assertRaises(ScriptError): + self.parser.eval('$eq(0,0,0)') + try: + self.parser.eval('$eq(1,1)') + except ScriptError as why: + self.fail("Function raised ScriptError: %s" % why) + + def test_cmd_with_wrong_argcount_if(self): + # $if() requires 2 or 3 arguments + with self.assertRaises(ScriptError): + self.parser.eval('$if(1)') + with self.assertRaises(ScriptError): + self.parser.eval('$if(1,a,b,c)') + try: + self.parser.eval('$if(1,a)') + except ScriptError as why: + self.fail("Function raised ScriptError: %s" % why) + try: + self.parser.eval('$if(1,a,b)') + except ScriptError as why: + self.fail("Function raised ScriptError: %s" % why) + def test_cmd_unset_simple(self): context = Metadata() context['title'] = u'Foo'