@@ -1911,6 +1911,9 @@ def parse_args(self, args=None, namespace=None):
19111911 return args
19121912
19131913 def parse_known_args (self , args = None , namespace = None ):
1914+ return self ._parse_known_args2 (args , namespace , intermixed = False )
1915+
1916+ def _parse_known_args2 (self , args , namespace , intermixed ):
19141917 if args is None :
19151918 # args default to the system args
19161919 args = _sys .argv [1 :]
@@ -1937,18 +1940,18 @@ def parse_known_args(self, args=None, namespace=None):
19371940 # parse the arguments and exit if there are any errors
19381941 if self .exit_on_error :
19391942 try :
1940- namespace , args = self ._parse_known_args (args , namespace )
1943+ namespace , args = self ._parse_known_args (args , namespace , intermixed )
19411944 except ArgumentError as err :
19421945 self .error (str (err ))
19431946 else :
1944- namespace , args = self ._parse_known_args (args , namespace )
1947+ namespace , args = self ._parse_known_args (args , namespace , intermixed )
19451948
19461949 if hasattr (namespace , _UNRECOGNIZED_ARGS_ATTR ):
19471950 args .extend (getattr (namespace , _UNRECOGNIZED_ARGS_ATTR ))
19481951 delattr (namespace , _UNRECOGNIZED_ARGS_ATTR )
19491952 return namespace , args
19501953
1951- def _parse_known_args (self , arg_strings , namespace ):
1954+ def _parse_known_args (self , arg_strings , namespace , intermixed ):
19521955 # replace arg strings that are file references
19531956 if self .fromfile_prefix_chars is not None :
19541957 arg_strings = self ._read_args_from_files (arg_strings )
@@ -2038,6 +2041,7 @@ def consume_optional(start_index):
20382041 # if we found no optional action, skip it
20392042 if action is None :
20402043 extras .append (arg_strings [start_index ])
2044+ extras_pattern .append ('O' )
20412045 return start_index + 1
20422046
20432047 # if there is an explicit argument, try to match the
@@ -2073,6 +2077,7 @@ def consume_optional(start_index):
20732077 sep = ''
20742078 else :
20752079 extras .append (char + explicit_arg )
2080+ extras_pattern .append ('O' )
20762081 stop = start_index + 1
20772082 break
20782083 # if the action expect exactly one argument, we've
@@ -2143,6 +2148,7 @@ def consume_positionals(start_index):
21432148 # consume Positionals and Optionals alternately, until we have
21442149 # passed the last option string
21452150 extras = []
2151+ extras_pattern = []
21462152 start_index = 0
21472153 if option_string_indices :
21482154 max_option_string_index = max (option_string_indices )
@@ -2155,7 +2161,7 @@ def consume_positionals(start_index):
21552161 index
21562162 for index in option_string_indices
21572163 if index >= start_index ])
2158- if start_index != next_option_string_index :
2164+ if not intermixed and start_index != next_option_string_index :
21592165 positionals_end_index = consume_positionals (start_index )
21602166
21612167 # only try to parse the next optional if we didn't consume
@@ -2171,16 +2177,35 @@ def consume_positionals(start_index):
21712177 if start_index not in option_string_indices :
21722178 strings = arg_strings [start_index :next_option_string_index ]
21732179 extras .extend (strings )
2180+ extras_pattern .extend (arg_strings_pattern [start_index :next_option_string_index ])
21742181 start_index = next_option_string_index
21752182
21762183 # consume the next optional and any arguments for it
21772184 start_index = consume_optional (start_index )
21782185
2179- # consume any positionals following the last Optional
2180- stop_index = consume_positionals (start_index )
2186+ if not intermixed :
2187+ # consume any positionals following the last Optional
2188+ stop_index = consume_positionals (start_index )
21812189
2182- # if we didn't consume all the argument strings, there were extras
2183- extras .extend (arg_strings [stop_index :])
2190+ # if we didn't consume all the argument strings, there were extras
2191+ extras .extend (arg_strings [stop_index :])
2192+ else :
2193+ extras .extend (arg_strings [start_index :])
2194+ extras_pattern .extend (arg_strings_pattern [start_index :])
2195+ extras_pattern = '' .join (extras_pattern )
2196+ assert len (extras_pattern ) == len (extras )
2197+ # consume all positionals
2198+ arg_strings = [s for s , c in zip (extras , extras_pattern ) if c != 'O' ]
2199+ arg_strings_pattern = extras_pattern .replace ('O' , '' )
2200+ stop_index = consume_positionals (0 )
2201+ # leave unknown optionals and non-consumed positionals in extras
2202+ for i , c in enumerate (extras_pattern ):
2203+ if not stop_index :
2204+ break
2205+ if c != 'O' :
2206+ stop_index -= 1
2207+ extras [i ] = None
2208+ extras = [s for s in extras if s is not None ]
21842209
21852210 # make sure all required actions were present and also convert
21862211 # action defaults which were not given as arguments
@@ -2446,10 +2471,6 @@ def parse_known_intermixed_args(self, args=None, namespace=None):
24462471 # are then parsed. If the parser definition is incompatible with the
24472472 # intermixed assumptions (e.g. use of REMAINDER, subparsers) a
24482473 # TypeError is raised.
2449- #
2450- # positionals are 'deactivated' by setting nargs and default to
2451- # SUPPRESS. This blocks the addition of that positional to the
2452- # namespace
24532474
24542475 positionals = self ._get_positional_actions ()
24552476 a = [action for action in positionals
@@ -2458,59 +2479,7 @@ def parse_known_intermixed_args(self, args=None, namespace=None):
24582479 raise TypeError ('parse_intermixed_args: positional arg'
24592480 ' with nargs=%s' % a [0 ].nargs )
24602481
2461- if [action .dest for group in self ._mutually_exclusive_groups
2462- for action in group ._group_actions if action in positionals ]:
2463- raise TypeError ('parse_intermixed_args: positional in'
2464- ' mutuallyExclusiveGroup' )
2465-
2466- try :
2467- save_usage = self .usage
2468- try :
2469- if self .usage is None :
2470- # capture the full usage for use in error messages
2471- self .usage = self .format_usage ()[7 :]
2472- for action in positionals :
2473- # deactivate positionals
2474- action .save_nargs = action .nargs
2475- # action.nargs = 0
2476- action .nargs = SUPPRESS
2477- action .save_default = action .default
2478- action .default = SUPPRESS
2479- namespace , remaining_args = self .parse_known_args (args ,
2480- namespace )
2481- for action in positionals :
2482- # remove the empty positional values from namespace
2483- if (hasattr (namespace , action .dest )
2484- and getattr (namespace , action .dest )== []):
2485- from warnings import warn
2486- warn ('Do not expect %s in %s' % (action .dest , namespace ))
2487- delattr (namespace , action .dest )
2488- finally :
2489- # restore nargs and usage before exiting
2490- for action in positionals :
2491- action .nargs = action .save_nargs
2492- action .default = action .save_default
2493- optionals = self ._get_optional_actions ()
2494- try :
2495- # parse positionals. optionals aren't normally required, but
2496- # they could be, so make sure they aren't.
2497- for action in optionals :
2498- action .save_required = action .required
2499- action .required = False
2500- for group in self ._mutually_exclusive_groups :
2501- group .save_required = group .required
2502- group .required = False
2503- namespace , extras = self .parse_known_args (remaining_args ,
2504- namespace )
2505- finally :
2506- # restore parser values before exiting
2507- for action in optionals :
2508- action .required = action .save_required
2509- for group in self ._mutually_exclusive_groups :
2510- group .required = group .save_required
2511- finally :
2512- self .usage = save_usage
2513- return namespace , extras
2482+ return self ._parse_known_args2 (args , namespace , intermixed = True )
25142483
25152484 # ========================
25162485 # Value conversion methods
0 commit comments