@@ -565,7 +565,8 @@ def _MakeParseFn(fn):
565565
566566 def _ParseFn (args ):
567567 """Parses the list of `args` into (varargs, kwargs), remaining_args."""
568- kwargs , remaining_args = _ParseKeywordArgs (args , all_args , fn_spec .varkw )
568+ kwargs , remaining_kwargs , remaining_args = \
569+ _ParseKeywordArgs (args , all_args , fn_spec .varkw )
569570
570571 # Note: _ParseArgs modifies kwargs.
571572 parsed_args , kwargs , remaining_args , capacity = _ParseArgs (
@@ -594,6 +595,7 @@ def _ParseFn(args):
594595 varargs [index ] = _ParseValue (value , None , None , metadata )
595596
596597 varargs = parsed_args + varargs
598+ remaining_args += remaining_kwargs
597599
598600 consumed_args = args [:len (args ) - len (remaining_args )]
599601 return (varargs , kwargs ), consumed_args , remaining_args , capacity
@@ -681,64 +683,72 @@ def _ParseKeywordArgs(args, fn_args, fn_keywords):
681683 fn_keywords: The argument name for **kwargs, or None if **kwargs not used
682684 Returns:
683685 kwargs: A dictionary mapping keywords to values.
686+ remaining_kwargs: A list of the unused kwargs from the original args.
684687 remaining_args: A list of the unused arguments from the original args.
685688 """
686689 kwargs = {}
687- if args :
688- remaining_args = []
689- skip_argument = False
690-
691- for index , argument in enumerate (args ):
692- if skip_argument :
693- skip_argument = False
694- continue
695-
696- arg_consumed = False
697- if argument .startswith ('--' ):
698- # This is a named argument; get its value from this arg or the next.
699- got_argument = False
700-
701- keyword = argument [2 :]
702- contains_equals = '=' in keyword
703- is_bool_syntax = (
704- not contains_equals and
705- (index + 1 == len (args ) or args [index + 1 ].startswith ('--' )))
706- if contains_equals :
707- keyword , value = keyword .split ('=' , 1 )
708- got_argument = True
709- elif is_bool_syntax :
710- # Since there's no next arg or the next arg is a Flag, we consider
711- # this flag to be a boolean.
712- got_argument = True
713- if keyword in fn_args :
714- value = 'True'
715- elif keyword .startswith ('no' ):
716- keyword = keyword [2 :]
717- value = 'False'
718- else :
719- value = 'True'
690+ remaining_kwargs = []
691+ remaining_args = []
692+
693+ if not args :
694+ return kwargs , remaining_kwargs , remaining_args
695+
696+ skip_argument = False
697+
698+ for index , argument in enumerate (args ):
699+ if skip_argument :
700+ skip_argument = False
701+ continue
702+
703+ arg_consumed = False
704+ if argument .startswith ('--' ):
705+ # This is a named argument; get its value from this arg or the next.
706+ got_argument = False
707+
708+ keyword = argument [2 :]
709+ contains_equals = '=' in keyword
710+ is_bool_syntax = (
711+ not contains_equals and
712+ (index + 1 == len (args ) or args [index + 1 ].startswith ('--' )))
713+ if contains_equals :
714+ keyword , value = keyword .split ('=' , 1 )
715+ got_argument = True
716+ elif is_bool_syntax :
717+ # Since there's no next arg or the next arg is a Flag, we consider
718+ # this flag to be a boolean.
719+ got_argument = True
720+ if keyword in fn_args :
721+ value = 'True'
722+ elif keyword .startswith ('no' ):
723+ keyword = keyword [2 :]
724+ value = 'False'
720725 else :
721- if index + 1 < len (args ):
722- value = args [index + 1 ]
723- got_argument = True
726+ value = 'True'
727+ else :
728+ if index + 1 < len (args ):
729+ value = args [index + 1 ]
730+ got_argument = True
724731
725- keyword = keyword .replace ('-' , '_' )
732+ keyword = keyword .replace ('-' , '_' )
726733
727- # In order for us to consume the argument as a keyword arg, we either:
728- # Need to be explicitly expecting the keyword, or we need to be
729- # accepting **kwargs.
730- if got_argument and (keyword in fn_args or fn_keywords ):
734+ # In order for us to consume the argument as a keyword arg, we either:
735+ # Need to be explicitly expecting the keyword, or we need to be
736+ # accepting **kwargs.
737+ if got_argument :
738+ skip_argument = not contains_equals and not is_bool_syntax
739+ arg_consumed = True
740+ if keyword in fn_args or fn_keywords :
731741 kwargs [keyword ] = value
732- skip_argument = not contains_equals and not is_bool_syntax
733- arg_consumed = True
742+ else :
743+ remaining_kwargs .append (argument )
744+ if skip_argument :
745+ remaining_kwargs .append (args [index + 1 ])
734746
735- if not arg_consumed :
736- # The argument was not consumed, so it is still a remaining argument.
737- remaining_args .append (argument )
738- else :
739- remaining_args = args
747+ if not arg_consumed :
748+ # The argument was not consumed, so it is still a remaining argument.
749+ remaining_args .append (argument )
740750
741- return kwargs , remaining_args
751+ return kwargs , remaining_kwargs , remaining_args
742752
743753
744754def _ParseValue (value , index , arg , metadata ):
0 commit comments