mercurial/parser.py
changeset 30753 c3a3896a9fa8
parent 30752 ffd324eaf994
child 31353 089e37802fb3
equal deleted inserted replaced
30752:ffd324eaf994 30753:c3a3896a9fa8
    88         t = self.parse(tokeniter)
    88         t = self.parse(tokeniter)
    89         if self._methods:
    89         if self._methods:
    90             return self.eval(t)
    90             return self.eval(t)
    91         return t
    91         return t
    92 
    92 
    93 def buildargsdict(trees, funcname, keys, keyvaluenode, keynode):
    93 def splitargspec(spec):
       
    94     """Parse spec of function arguments into (poskeys, varkey, keys)
       
    95 
       
    96     >>> splitargspec('')
       
    97     ([], None, [])
       
    98     >>> splitargspec('foo bar')
       
    99     ([], None, ['foo', 'bar'])
       
   100     >>> splitargspec('foo *bar baz')
       
   101     (['foo'], 'bar', ['baz'])
       
   102     >>> splitargspec('*foo')
       
   103     ([], 'foo', [])
       
   104     """
       
   105     pre, sep, post = spec.partition('*')
       
   106     pres = pre.split()
       
   107     posts = post.split()
       
   108     if sep:
       
   109         if not posts:
       
   110             raise error.ProgrammingError('no *varkey name provided')
       
   111         return pres, posts[0], posts[1:]
       
   112     return [], None, pres
       
   113 
       
   114 def buildargsdict(trees, funcname, argspec, keyvaluenode, keynode):
    94     """Build dict from list containing positional and keyword arguments
   115     """Build dict from list containing positional and keyword arguments
    95 
   116 
    96     Invalid keywords or too many positional arguments are rejected, but
   117     Arguments are specified by a tuple of ``(poskeys, varkey, keys)`` where
    97     missing arguments are just omitted.
   118 
       
   119     - ``poskeys``: list of names of positional arguments
       
   120     - ``varkey``: optional argument name that takes up remainder
       
   121     - ``keys``: list of names that can be either positional or keyword arguments
       
   122 
       
   123     If ``varkey`` specified, all ``keys`` must be given as keyword arguments.
       
   124 
       
   125     Invalid keywords, too few positional arguments, or too many positional
       
   126     arguments are rejected, but missing keyword arguments are just omitted.
    98     """
   127     """
       
   128     poskeys, varkey, keys = argspec
    99     kwstart = next((i for i, x in enumerate(trees) if x[0] == keyvaluenode),
   129     kwstart = next((i for i, x in enumerate(trees) if x[0] == keyvaluenode),
   100                    len(trees))
   130                    len(trees))
   101     if len(trees) > len(keys):
   131     if kwstart < len(poskeys):
       
   132         raise error.ParseError(_("%(func)s takes at least %(nargs)d positional "
       
   133                                  "arguments")
       
   134                                % {'func': funcname, 'nargs': len(poskeys)})
       
   135     if not varkey and len(trees) > len(poskeys) + len(keys):
   102         raise error.ParseError(_("%(func)s takes at most %(nargs)d arguments")
   136         raise error.ParseError(_("%(func)s takes at most %(nargs)d arguments")
   103                                % {'func': funcname, 'nargs': len(keys)})
   137                                % {'func': funcname,
       
   138                                   'nargs': len(poskeys) + len(keys)})
   104     args = {}
   139     args = {}
   105     # consume positional arguments
   140     # consume positional arguments
   106     for k, x in zip(keys, trees[:kwstart]):
   141     for k, x in zip(poskeys, trees[:kwstart]):
   107         args[k] = x
   142         args[k] = x
   108     assert len(args) == kwstart
   143     if varkey:
       
   144         args[varkey] = trees[len(args):kwstart]
       
   145     else:
       
   146         for k, x in zip(keys, trees[len(args):kwstart]):
       
   147             args[k] = x
   109     # remainder should be keyword arguments
   148     # remainder should be keyword arguments
   110     for x in trees[kwstart:]:
   149     for x in trees[kwstart:]:
   111         if x[0] != keyvaluenode or x[1][0] != keynode:
   150         if x[0] != keyvaluenode or x[1][0] != keynode:
   112             raise error.ParseError(_("%(func)s got an invalid argument")
   151             raise error.ParseError(_("%(func)s got an invalid argument")
   113                                    % {'func': funcname})
   152                                    % {'func': funcname})