revset: add function to build dict of positional and keyword arguments

Keyword arguments will be convenient for functions that will take more than
one optional or boolean flags. For example,

  file(pattern[, subrepos=false])
  subrepo([[pattern], status])

Because I don't think all functions should accept key=value syntax, getkwargs()
does not support variadic functions such as 'ancestor(*changeset)'.

The core logic is placed in the parser module because keyword arguments will
be more useful in the templater, where functions take more options. Test cases
will be added by the next patch.
This commit is contained in:
Yuya Nishihara 2015-06-27 17:25:01 +09:00
parent 411c9c1693
commit d1927459b6
2 changed files with 36 additions and 0 deletions

View File

@ -91,6 +91,38 @@ class parser(object):
return self.eval(t)
return t
def buildargsdict(trees, funcname, keys, keyvaluenode, keynode):
"""Build dict from list containing positional and keyword arguments
Invalid keywords or too many positional arguments are rejected, but
missing arguments are just omitted.
"""
if len(trees) > len(keys):
raise error.ParseError(_("%(func)s takes at most %(nargs)d arguments")
% {'func': funcname, 'nargs': len(keys)})
args = {}
# consume positional arguments
for k, x in zip(keys, trees):
if x[0] == keyvaluenode:
break
args[k] = x
# remainder should be keyword arguments
for x in trees[len(args):]:
if x[0] != keyvaluenode or x[1][0] != keynode:
raise error.ParseError(_("%(func)s got an invalid argument")
% {'func': funcname})
k = x[1][1]
if k not in keys:
raise error.ParseError(_("%(func)s got an unexpected keyword "
"argument '%(key)s'")
% {'func': funcname, 'key': k})
if k in args:
raise error.ParseError(_("%(func)s got multiple values for keyword "
"argument '%(key)s'")
% {'func': funcname, 'key': k})
args[k] = x[2]
return args
def _prettyformat(tree, leafnodes, level, lines):
if not isinstance(tree, tuple) or tree[0] in leafnodes:
lines.append((level, str(tree)))

View File

@ -282,6 +282,10 @@ def getargs(x, min, max, err):
raise error.ParseError(err)
return l
def getkwargs(x, funcname, keys):
return parser.buildargsdict(getlist(x), funcname, keys.split(),
keyvaluenode='keyvalue', keynode='symbol')
def isvalidsymbol(tree):
"""Examine whether specified ``tree`` is valid ``symbol`` or not
"""