mercurial/parser.py
changeset 31921 2156934b7917
parent 31920 a98540ea1e42
child 31922 0f41f1e3c75c
equal deleted inserted replaced
31920:a98540ea1e42 31921:2156934b7917
    92         if self._methods:
    92         if self._methods:
    93             return self.eval(t)
    93             return self.eval(t)
    94         return t
    94         return t
    95 
    95 
    96 def splitargspec(spec):
    96 def splitargspec(spec):
    97     """Parse spec of function arguments into (poskeys, varkey, keys)
    97     """Parse spec of function arguments into (poskeys, varkey, keys, optkey)
    98 
    98 
    99     >>> splitargspec('')
    99     >>> splitargspec('')
   100     ([], None, [])
   100     ([], None, [], None)
   101     >>> splitargspec('foo bar')
   101     >>> splitargspec('foo bar')
   102     ([], None, ['foo', 'bar'])
   102     ([], None, ['foo', 'bar'], None)
   103     >>> splitargspec('foo *bar baz')
   103     >>> splitargspec('foo *bar baz **qux')
   104     (['foo'], 'bar', ['baz'])
   104     (['foo'], 'bar', ['baz'], 'qux')
   105     >>> splitargspec('*foo')
   105     >>> splitargspec('*foo')
   106     ([], 'foo', [])
   106     ([], 'foo', [], None)
       
   107     >>> splitargspec('**foo')
       
   108     ([], None, [], 'foo')
   107     """
   109     """
   108     pre, sep, post = spec.partition('*')
   110     optkey = None
       
   111     pre, sep, post = spec.partition('**')
       
   112     if sep:
       
   113         posts = post.split()
       
   114         if not posts:
       
   115             raise error.ProgrammingError('no **optkey name provided')
       
   116         if len(posts) > 1:
       
   117             raise error.ProgrammingError('excessive **optkey names provided')
       
   118         optkey = posts[0]
       
   119 
       
   120     pre, sep, post = pre.partition('*')
   109     pres = pre.split()
   121     pres = pre.split()
   110     posts = post.split()
   122     posts = post.split()
   111     if sep:
   123     if sep:
   112         if not posts:
   124         if not posts:
   113             raise error.ProgrammingError('no *varkey name provided')
   125             raise error.ProgrammingError('no *varkey name provided')
   114         return pres, posts[0], posts[1:]
   126         return pres, posts[0], posts[1:], optkey
   115     return [], None, pres
   127     return [], None, pres, optkey
   116 
   128 
   117 def buildargsdict(trees, funcname, argspec, keyvaluenode, keynode):
   129 def buildargsdict(trees, funcname, argspec, keyvaluenode, keynode):
   118     """Build dict from list containing positional and keyword arguments
   130     """Build dict from list containing positional and keyword arguments
   119 
   131 
   120     Arguments are specified by a tuple of ``(poskeys, varkey, keys)`` where
   132     Arguments are specified by a tuple of ``(poskeys, varkey, keys, optkey)``
       
   133     where
   121 
   134 
   122     - ``poskeys``: list of names of positional arguments
   135     - ``poskeys``: list of names of positional arguments
   123     - ``varkey``: optional argument name that takes up remainder
   136     - ``varkey``: optional argument name that takes up remainder
   124     - ``keys``: list of names that can be either positional or keyword arguments
   137     - ``keys``: list of names that can be either positional or keyword arguments
       
   138     - ``optkey``: optional argument name that takes up excess keyword arguments
   125 
   139 
   126     If ``varkey`` specified, all ``keys`` must be given as keyword arguments.
   140     If ``varkey`` specified, all ``keys`` must be given as keyword arguments.
   127 
   141 
   128     Invalid keywords, too few positional arguments, or too many positional
   142     Invalid keywords, too few positional arguments, or too many positional
   129     arguments are rejected, but missing keyword arguments are just omitted.
   143     arguments are rejected, but missing keyword arguments are just omitted.
   130     """
   144     """
   131     poskeys, varkey, keys = argspec
   145     poskeys, varkey, keys, optkey = argspec
   132     kwstart = next((i for i, x in enumerate(trees) if x[0] == keyvaluenode),
   146     kwstart = next((i for i, x in enumerate(trees) if x[0] == keyvaluenode),
   133                    len(trees))
   147                    len(trees))
   134     if kwstart < len(poskeys):
   148     if kwstart < len(poskeys):
   135         raise error.ParseError(_("%(func)s takes at least %(nargs)d positional "
   149         raise error.ParseError(_("%(func)s takes at least %(nargs)d positional "
   136                                  "arguments")
   150                                  "arguments")
   148         args[varkey] = trees[len(args):kwstart]
   162         args[varkey] = trees[len(args):kwstart]
   149     else:
   163     else:
   150         for k, x in zip(keys, trees[len(args):kwstart]):
   164         for k, x in zip(keys, trees[len(args):kwstart]):
   151             args[k] = x
   165             args[k] = x
   152     # remainder should be keyword arguments
   166     # remainder should be keyword arguments
       
   167     if optkey:
       
   168         args[optkey] = {}
   153     for x in trees[kwstart:]:
   169     for x in trees[kwstart:]:
   154         if x[0] != keyvaluenode or x[1][0] != keynode:
   170         if x[0] != keyvaluenode or x[1][0] != keynode:
   155             raise error.ParseError(_("%(func)s got an invalid argument")
   171             raise error.ParseError(_("%(func)s got an invalid argument")
   156                                    % {'func': funcname})
   172                                    % {'func': funcname})
   157         k = x[1][1]
   173         k = x[1][1]
   158         if k not in keys:
   174         if k in keys:
       
   175             d = args
       
   176         elif not optkey:
   159             raise error.ParseError(_("%(func)s got an unexpected keyword "
   177             raise error.ParseError(_("%(func)s got an unexpected keyword "
   160                                      "argument '%(key)s'")
   178                                      "argument '%(key)s'")
   161                                    % {'func': funcname, 'key': k})
   179                                    % {'func': funcname, 'key': k})
   162         if k in args:
   180         else:
       
   181             d = args[optkey]
       
   182         if k in d:
   163             raise error.ParseError(_("%(func)s got multiple values for keyword "
   183             raise error.ParseError(_("%(func)s got multiple values for keyword "
   164                                      "argument '%(key)s'")
   184                                      "argument '%(key)s'")
   165                                    % {'func': funcname, 'key': k})
   185                                    % {'func': funcname, 'key': k})
   166         args[k] = x[2]
   186         d[k] = x[2]
   167     return args
   187     return args
   168 
   188 
   169 def unescapestr(s):
   189 def unescapestr(s):
   170     try:
   190     try:
   171         return util.unescapestr(s)
   191         return util.unescapestr(s)