@@ -1924,6 +1924,9 @@ def parse_args(self, args=None, namespace=None):
1924
1924
return args
1925
1925
1926
1926
def parse_known_args (self , args = None , namespace = None ):
1927
+ return self ._parse_known_args2 (args , namespace , intermixed = False )
1928
+
1929
+ def _parse_known_args2 (self , args , namespace , intermixed ):
1927
1930
if args is None :
1928
1931
# args default to the system args
1929
1932
args = _sys .argv [1 :]
@@ -1950,18 +1953,18 @@ def parse_known_args(self, args=None, namespace=None):
1950
1953
# parse the arguments and exit if there are any errors
1951
1954
if self .exit_on_error :
1952
1955
try :
1953
- namespace , args = self ._parse_known_args (args , namespace )
1956
+ namespace , args = self ._parse_known_args (args , namespace , intermixed )
1954
1957
except ArgumentError as err :
1955
1958
self .error (str (err ))
1956
1959
else :
1957
- namespace , args = self ._parse_known_args (args , namespace )
1960
+ namespace , args = self ._parse_known_args (args , namespace , intermixed )
1958
1961
1959
1962
if hasattr (namespace , _UNRECOGNIZED_ARGS_ATTR ):
1960
1963
args .extend (getattr (namespace , _UNRECOGNIZED_ARGS_ATTR ))
1961
1964
delattr (namespace , _UNRECOGNIZED_ARGS_ATTR )
1962
1965
return namespace , args
1963
1966
1964
- def _parse_known_args (self , arg_strings , namespace ):
1967
+ def _parse_known_args (self , arg_strings , namespace , intermixed ):
1965
1968
# replace arg strings that are file references
1966
1969
if self .fromfile_prefix_chars is not None :
1967
1970
arg_strings = self ._read_args_from_files (arg_strings )
@@ -2052,6 +2055,7 @@ def consume_optional(start_index):
2052
2055
# if we found no optional action, skip it
2053
2056
if action is None :
2054
2057
extras .append (arg_strings [start_index ])
2058
+ extras_pattern .append ('O' )
2055
2059
return start_index + 1
2056
2060
2057
2061
# if there is an explicit argument, try to match the
@@ -2087,6 +2091,7 @@ def consume_optional(start_index):
2087
2091
sep = ''
2088
2092
else :
2089
2093
extras .append (char + explicit_arg )
2094
+ extras_pattern .append ('O' )
2090
2095
stop = start_index + 1
2091
2096
break
2092
2097
# if the action expect exactly one argument, we've
@@ -2165,6 +2170,7 @@ def consume_positionals(start_index):
2165
2170
# consume Positionals and Optionals alternately, until we have
2166
2171
# passed the last option string
2167
2172
extras = []
2173
+ extras_pattern = []
2168
2174
start_index = 0
2169
2175
if option_string_indices :
2170
2176
max_option_string_index = max (option_string_indices )
@@ -2178,7 +2184,7 @@ def consume_positionals(start_index):
2178
2184
if next_option_string_index in option_string_indices :
2179
2185
break
2180
2186
next_option_string_index += 1
2181
- if start_index != next_option_string_index :
2187
+ if not intermixed and start_index != next_option_string_index :
2182
2188
positionals_end_index = consume_positionals (start_index )
2183
2189
2184
2190
# only try to parse the next optional if we didn't consume
@@ -2194,16 +2200,35 @@ def consume_positionals(start_index):
2194
2200
if start_index not in option_string_indices :
2195
2201
strings = arg_strings [start_index :next_option_string_index ]
2196
2202
extras .extend (strings )
2203
+ extras_pattern .extend (arg_strings_pattern [start_index :next_option_string_index ])
2197
2204
start_index = next_option_string_index
2198
2205
2199
2206
# consume the next optional and any arguments for it
2200
2207
start_index = consume_optional (start_index )
2201
2208
2202
- # consume any positionals following the last Optional
2203
- stop_index = consume_positionals (start_index )
2209
+ if not intermixed :
2210
+ # consume any positionals following the last Optional
2211
+ stop_index = consume_positionals (start_index )
2204
2212
2205
- # if we didn't consume all the argument strings, there were extras
2206
- extras .extend (arg_strings [stop_index :])
2213
+ # if we didn't consume all the argument strings, there were extras
2214
+ extras .extend (arg_strings [stop_index :])
2215
+ else :
2216
+ extras .extend (arg_strings [start_index :])
2217
+ extras_pattern .extend (arg_strings_pattern [start_index :])
2218
+ extras_pattern = '' .join (extras_pattern )
2219
+ assert len (extras_pattern ) == len (extras )
2220
+ # consume all positionals
2221
+ arg_strings = [s for s , c in zip (extras , extras_pattern ) if c != 'O' ]
2222
+ arg_strings_pattern = extras_pattern .replace ('O' , '' )
2223
+ stop_index = consume_positionals (0 )
2224
+ # leave unknown optionals and non-consumed positionals in extras
2225
+ for i , c in enumerate (extras_pattern ):
2226
+ if not stop_index :
2227
+ break
2228
+ if c != 'O' :
2229
+ stop_index -= 1
2230
+ extras [i ] = None
2231
+ extras = [s for s in extras if s is not None ]
2207
2232
2208
2233
# make sure all required actions were present and also convert
2209
2234
# action defaults which were not given as arguments
@@ -2469,10 +2494,6 @@ def parse_known_intermixed_args(self, args=None, namespace=None):
2469
2494
# are then parsed. If the parser definition is incompatible with the
2470
2495
# intermixed assumptions (e.g. use of REMAINDER, subparsers) a
2471
2496
# TypeError is raised.
2472
- #
2473
- # positionals are 'deactivated' by setting nargs and default to
2474
- # SUPPRESS. This blocks the addition of that positional to the
2475
- # namespace
2476
2497
2477
2498
positionals = self ._get_positional_actions ()
2478
2499
a = [action for action in positionals
@@ -2481,59 +2502,7 @@ def parse_known_intermixed_args(self, args=None, namespace=None):
2481
2502
raise TypeError ('parse_intermixed_args: positional arg'
2482
2503
' with nargs=%s' % a [0 ].nargs )
2483
2504
2484
- if [action .dest for group in self ._mutually_exclusive_groups
2485
- for action in group ._group_actions if action in positionals ]:
2486
- raise TypeError ('parse_intermixed_args: positional in'
2487
- ' mutuallyExclusiveGroup' )
2488
-
2489
- try :
2490
- save_usage = self .usage
2491
- try :
2492
- if self .usage is None :
2493
- # capture the full usage for use in error messages
2494
- self .usage = self .format_usage ()[7 :]
2495
- for action in positionals :
2496
- # deactivate positionals
2497
- action .save_nargs = action .nargs
2498
- # action.nargs = 0
2499
- action .nargs = SUPPRESS
2500
- action .save_default = action .default
2501
- action .default = SUPPRESS
2502
- namespace , remaining_args = self .parse_known_args (args ,
2503
- namespace )
2504
- for action in positionals :
2505
- # remove the empty positional values from namespace
2506
- if (hasattr (namespace , action .dest )
2507
- and getattr (namespace , action .dest )== []):
2508
- from warnings import warn
2509
- warn ('Do not expect %s in %s' % (action .dest , namespace ))
2510
- delattr (namespace , action .dest )
2511
- finally :
2512
- # restore nargs and usage before exiting
2513
- for action in positionals :
2514
- action .nargs = action .save_nargs
2515
- action .default = action .save_default
2516
- optionals = self ._get_optional_actions ()
2517
- try :
2518
- # parse positionals. optionals aren't normally required, but
2519
- # they could be, so make sure they aren't.
2520
- for action in optionals :
2521
- action .save_required = action .required
2522
- action .required = False
2523
- for group in self ._mutually_exclusive_groups :
2524
- group .save_required = group .required
2525
- group .required = False
2526
- namespace , extras = self .parse_known_args (remaining_args ,
2527
- namespace )
2528
- finally :
2529
- # restore parser values before exiting
2530
- for action in optionals :
2531
- action .required = action .save_required
2532
- for group in self ._mutually_exclusive_groups :
2533
- group .required = group .save_required
2534
- finally :
2535
- self .usage = save_usage
2536
- return namespace , extras
2505
+ return self ._parse_known_args2 (args , namespace , intermixed = True )
2537
2506
2538
2507
# ========================
2539
2508
# Value conversion methods
0 commit comments