@@ -1896,6 +1896,9 @@ def parse_args(self, args=None, namespace=None):
18961896 return args
18971897
18981898 def parse_known_args (self , args = None , namespace = None ):
1899+ return self ._parse_known_args2 (args , namespace , intermixed = False )
1900+
1901+ def _parse_known_args2 (self , args , namespace , intermixed ):
18991902 if args is None :
19001903 # args default to the system args
19011904 args = _sys .argv [1 :]
@@ -1922,18 +1925,18 @@ def parse_known_args(self, args=None, namespace=None):
19221925 # parse the arguments and exit if there are any errors
19231926 if self .exit_on_error :
19241927 try :
1925- namespace , args = self ._parse_known_args (args , namespace )
1928+ namespace , args = self ._parse_known_args (args , namespace , intermixed )
19261929 except ArgumentError as err :
19271930 self .error (str (err ))
19281931 else :
1929- namespace , args = self ._parse_known_args (args , namespace )
1932+ namespace , args = self ._parse_known_args (args , namespace , intermixed )
19301933
19311934 if hasattr (namespace , _UNRECOGNIZED_ARGS_ATTR ):
19321935 args .extend (getattr (namespace , _UNRECOGNIZED_ARGS_ATTR ))
19331936 delattr (namespace , _UNRECOGNIZED_ARGS_ATTR )
19341937 return namespace , args
19351938
1936- def _parse_known_args (self , arg_strings , namespace ):
1939+ def _parse_known_args (self , arg_strings , namespace , intermixed ):
19371940 # replace arg strings that are file references
19381941 if self .fromfile_prefix_chars is not None :
19391942 arg_strings = self ._read_args_from_files (arg_strings )
@@ -2024,6 +2027,7 @@ def consume_optional(start_index):
20242027 # if we found no optional action, skip it
20252028 if action is None :
20262029 extras .append (arg_strings [start_index ])
2030+ extras_pattern .append ('O' )
20272031 return start_index + 1
20282032
20292033 # if there is an explicit argument, try to match the
@@ -2059,6 +2063,7 @@ def consume_optional(start_index):
20592063 sep = ''
20602064 else :
20612065 extras .append (char + explicit_arg )
2066+ extras_pattern .append ('O' )
20622067 stop = start_index + 1
20632068 break
20642069 # if the action expect exactly one argument, we've
@@ -2137,6 +2142,7 @@ def consume_positionals(start_index):
21372142 # consume Positionals and Optionals alternately, until we have
21382143 # passed the last option string
21392144 extras = []
2145+ extras_pattern = []
21402146 start_index = 0
21412147 if option_string_indices :
21422148 max_option_string_index = max (option_string_indices )
@@ -2150,7 +2156,7 @@ def consume_positionals(start_index):
21502156 if next_option_string_index in option_string_indices :
21512157 break
21522158 next_option_string_index += 1
2153- if start_index != next_option_string_index :
2159+ if not intermixed and start_index != next_option_string_index :
21542160 positionals_end_index = consume_positionals (start_index )
21552161
21562162 # only try to parse the next optional if we didn't consume
@@ -2166,16 +2172,35 @@ def consume_positionals(start_index):
21662172 if start_index not in option_string_indices :
21672173 strings = arg_strings [start_index :next_option_string_index ]
21682174 extras .extend (strings )
2175+ extras_pattern .extend (arg_strings_pattern [start_index :next_option_string_index ])
21692176 start_index = next_option_string_index
21702177
21712178 # consume the next optional and any arguments for it
21722179 start_index = consume_optional (start_index )
21732180
2174- # consume any positionals following the last Optional
2175- stop_index = consume_positionals (start_index )
2181+ if not intermixed :
2182+ # consume any positionals following the last Optional
2183+ stop_index = consume_positionals (start_index )
21762184
2177- # if we didn't consume all the argument strings, there were extras
2178- extras .extend (arg_strings [stop_index :])
2185+ # if we didn't consume all the argument strings, there were extras
2186+ extras .extend (arg_strings [stop_index :])
2187+ else :
2188+ extras .extend (arg_strings [start_index :])
2189+ extras_pattern .extend (arg_strings_pattern [start_index :])
2190+ extras_pattern = '' .join (extras_pattern )
2191+ assert len (extras_pattern ) == len (extras )
2192+ # consume all positionals
2193+ arg_strings = [s for s , c in zip (extras , extras_pattern ) if c != 'O' ]
2194+ arg_strings_pattern = extras_pattern .replace ('O' , '' )
2195+ stop_index = consume_positionals (0 )
2196+ # leave unknown optionals and non-consumed positionals in extras
2197+ for i , c in enumerate (extras_pattern ):
2198+ if not stop_index :
2199+ break
2200+ if c != 'O' :
2201+ stop_index -= 1
2202+ extras [i ] = None
2203+ extras = [s for s in extras if s is not None ]
21792204
21802205 # make sure all required actions were present and also convert
21812206 # action defaults which were not given as arguments
@@ -2441,10 +2466,6 @@ def parse_known_intermixed_args(self, args=None, namespace=None):
24412466 # are then parsed. If the parser definition is incompatible with the
24422467 # intermixed assumptions (e.g. use of REMAINDER, subparsers) a
24432468 # TypeError is raised.
2444- #
2445- # positionals are 'deactivated' by setting nargs and default to
2446- # SUPPRESS. This blocks the addition of that positional to the
2447- # namespace
24482469
24492470 positionals = self ._get_positional_actions ()
24502471 a = [action for action in positionals
@@ -2453,59 +2474,7 @@ def parse_known_intermixed_args(self, args=None, namespace=None):
24532474 raise TypeError ('parse_intermixed_args: positional arg'
24542475 ' with nargs=%s' % a [0 ].nargs )
24552476
2456- if [action .dest for group in self ._mutually_exclusive_groups
2457- for action in group ._group_actions if action in positionals ]:
2458- raise TypeError ('parse_intermixed_args: positional in'
2459- ' mutuallyExclusiveGroup' )
2460-
2461- try :
2462- save_usage = self .usage
2463- try :
2464- if self .usage is None :
2465- # capture the full usage for use in error messages
2466- self .usage = self .format_usage ()[7 :]
2467- for action in positionals :
2468- # deactivate positionals
2469- action .save_nargs = action .nargs
2470- # action.nargs = 0
2471- action .nargs = SUPPRESS
2472- action .save_default = action .default
2473- action .default = SUPPRESS
2474- namespace , remaining_args = self .parse_known_args (args ,
2475- namespace )
2476- for action in positionals :
2477- # remove the empty positional values from namespace
2478- if (hasattr (namespace , action .dest )
2479- and getattr (namespace , action .dest )== []):
2480- from warnings import warn
2481- warn ('Do not expect %s in %s' % (action .dest , namespace ))
2482- delattr (namespace , action .dest )
2483- finally :
2484- # restore nargs and usage before exiting
2485- for action in positionals :
2486- action .nargs = action .save_nargs
2487- action .default = action .save_default
2488- optionals = self ._get_optional_actions ()
2489- try :
2490- # parse positionals. optionals aren't normally required, but
2491- # they could be, so make sure they aren't.
2492- for action in optionals :
2493- action .save_required = action .required
2494- action .required = False
2495- for group in self ._mutually_exclusive_groups :
2496- group .save_required = group .required
2497- group .required = False
2498- namespace , extras = self .parse_known_args (remaining_args ,
2499- namespace )
2500- finally :
2501- # restore parser values before exiting
2502- for action in optionals :
2503- action .required = action .save_required
2504- for group in self ._mutually_exclusive_groups :
2505- group .required = group .save_required
2506- finally :
2507- self .usage = save_usage
2508- return namespace , extras
2477+ return self ._parse_known_args2 (args , namespace , intermixed = True )
25092478
25102479 # ========================
25112480 # Value conversion methods
0 commit comments