@@ -1224,7 +1224,8 @@ def __call__(self, parser, namespace, values, option_string=None):
12241224 setattr (namespace , key , value )
12251225
12261226 if arg_strings :
1227- vars (namespace ).setdefault (_UNRECOGNIZED_ARGS_ATTR , [])
1227+ if not hasattr (namespace , _UNRECOGNIZED_ARGS_ATTR ):
1228+ setattr (namespace , _UNRECOGNIZED_ARGS_ATTR , [])
12281229 getattr (namespace , _UNRECOGNIZED_ARGS_ATTR ).extend (arg_strings )
12291230
12301231class _ExtendAction (_AppendAction ):
@@ -1927,11 +1928,11 @@ def _parse_known_args(self, arg_strings, namespace):
19271928 # otherwise, add the arg to the arg strings
19281929 # and note the index if it was an option
19291930 else :
1930- option_tuple = self ._parse_optional (arg_string )
1931- if option_tuple is None :
1931+ option_tuples = self ._parse_optional (arg_string )
1932+ if option_tuples is None :
19321933 pattern = 'A'
19331934 else :
1934- option_string_indices [i ] = option_tuple
1935+ option_string_indices [i ] = option_tuples
19351936 pattern = 'O'
19361937 arg_string_pattern_parts .append (pattern )
19371938
@@ -1966,8 +1967,16 @@ def take_action(action, argument_strings, option_string=None):
19661967 def consume_optional (start_index ):
19671968
19681969 # get the optional identified at this index
1969- option_tuple = option_string_indices [start_index ]
1970- action , option_string , sep , explicit_arg = option_tuple
1970+ option_tuples = option_string_indices [start_index ]
1971+ # if multiple actions match, the option string was ambiguous
1972+ if len (option_tuples ) > 1 :
1973+ options = ', ' .join ([option_string
1974+ for action , option_string , sep , explicit_arg in option_tuples ])
1975+ args = {'option' : arg_string , 'matches' : options }
1976+ msg = _ ('ambiguous option: %(option)s could match %(matches)s' )
1977+ raise ArgumentError (None , msg % args )
1978+
1979+ action , option_string , sep , explicit_arg = option_tuples [0 ]
19711980
19721981 # identify additional optionals in the same arg string
19731982 # (e.g. -xyz is the same as -x -y -z if no args are required)
@@ -2253,7 +2262,7 @@ def _parse_optional(self, arg_string):
22532262 # if the option string is present in the parser, return the action
22542263 if arg_string in self ._option_string_actions :
22552264 action = self ._option_string_actions [arg_string ]
2256- return action , arg_string , None , None
2265+ return [( action , arg_string , None , None )]
22572266
22582267 # if it's just a single character, it was meant to be positional
22592268 if len (arg_string ) == 1 :
@@ -2263,25 +2272,14 @@ def _parse_optional(self, arg_string):
22632272 option_string , sep , explicit_arg = arg_string .partition ('=' )
22642273 if sep and option_string in self ._option_string_actions :
22652274 action = self ._option_string_actions [option_string ]
2266- return action , option_string , sep , explicit_arg
2275+ return [( action , option_string , sep , explicit_arg )]
22672276
22682277 # search through all possible prefixes of the option string
22692278 # and all actions in the parser for possible interpretations
22702279 option_tuples = self ._get_option_tuples (arg_string )
22712280
2272- # if multiple actions match, the option string was ambiguous
2273- if len (option_tuples ) > 1 :
2274- options = ', ' .join ([option_string
2275- for action , option_string , sep , explicit_arg in option_tuples ])
2276- args = {'option' : arg_string , 'matches' : options }
2277- msg = _ ('ambiguous option: %(option)s could match %(matches)s' )
2278- raise ArgumentError (None , msg % args )
2279-
2280- # if exactly one action matched, this segmentation is good,
2281- # so return the parsed action
2282- elif len (option_tuples ) == 1 :
2283- option_tuple , = option_tuples
2284- return option_tuple
2281+ if option_tuples :
2282+ return option_tuples
22852283
22862284 # if it was not found as an option, but it looks like a negative
22872285 # number, it was meant to be positional
@@ -2296,7 +2294,7 @@ def _parse_optional(self, arg_string):
22962294
22972295 # it was meant to be an optional but there is no such option
22982296 # in this parser (though it might be a valid option in a subparser)
2299- return None , arg_string , None , None
2297+ return [( None , arg_string , None , None )]
23002298
23012299 def _get_option_tuples (self , option_string ):
23022300 result = []
@@ -2319,7 +2317,9 @@ def _get_option_tuples(self, option_string):
23192317 # but multiple character options always have to have their argument
23202318 # separate
23212319 elif option_string [0 ] in chars and option_string [1 ] not in chars :
2322- option_prefix = option_string
2320+ option_prefix , sep , explicit_arg = option_string .partition ('=' )
2321+ if not sep :
2322+ sep = explicit_arg = None
23232323 short_option_prefix = option_string [:2 ]
23242324 short_explicit_arg = option_string [2 :]
23252325
@@ -2328,9 +2328,9 @@ def _get_option_tuples(self, option_string):
23282328 action = self ._option_string_actions [option_string ]
23292329 tup = action , option_string , '' , short_explicit_arg
23302330 result .append (tup )
2331- elif option_string .startswith (option_prefix ):
2331+ elif self . allow_abbrev and option_string .startswith (option_prefix ):
23322332 action = self ._option_string_actions [option_string ]
2333- tup = action , option_string , None , None
2333+ tup = action , option_string , sep , explicit_arg
23342334 result .append (tup )
23352335
23362336 # shouldn't ever get here
@@ -2344,43 +2344,40 @@ def _get_nargs_pattern(self, action):
23442344 # in all examples below, we have to allow for '--' args
23452345 # which are represented as '-' in the pattern
23462346 nargs = action .nargs
2347+ # if this is an optional action, -- is not allowed
2348+ option = action .option_strings
23472349
23482350 # the default (None) is assumed to be a single argument
23492351 if nargs is None :
2350- nargs_pattern = '(-*A-*)'
2352+ nargs_pattern = '([A])' if option else '( -*A-*)'
23512353
23522354 # allow zero or one arguments
23532355 elif nargs == OPTIONAL :
2354- nargs_pattern = '(-*A?-*)'
2356+ nargs_pattern = '(A?)' if option else '( -*A?-*)'
23552357
23562358 # allow zero or more arguments
23572359 elif nargs == ZERO_OR_MORE :
2358- nargs_pattern = '(-*[A-]*)'
2360+ nargs_pattern = '(A*)' if option else '( -*[A-]*)'
23592361
23602362 # allow one or more arguments
23612363 elif nargs == ONE_OR_MORE :
2362- nargs_pattern = '(-*A[A-]*)'
2364+ nargs_pattern = '(A+)' if option else '( -*A[A-]*)'
23632365
23642366 # allow any number of options or arguments
23652367 elif nargs == REMAINDER :
2366- nargs_pattern = '([- AO]*)'
2368+ nargs_pattern = '([AO]*)' if option else '(. *)'
23672369
23682370 # allow one argument followed by any number of options or arguments
23692371 elif nargs == PARSER :
2370- nargs_pattern = '(-*A[-AO]*)'
2372+ nargs_pattern = '(A[AO]*)' if option else '( -*A[-AO]*)'
23712373
23722374 # suppress action, like nargs=0
23732375 elif nargs == SUPPRESS :
2374- nargs_pattern = '(-* -*)'
2376+ nargs_pattern = '()' if option else '( -*)'
23752377
23762378 # all others should be integers
23772379 else :
2378- nargs_pattern = '(-*%s-*)' % '-*' .join ('A' * nargs )
2379-
2380- # if this is an optional action, -- is not allowed
2381- if action .option_strings :
2382- nargs_pattern = nargs_pattern .replace ('-*' , '' )
2383- nargs_pattern = nargs_pattern .replace ('-' , '' )
2380+ nargs_pattern = '([AO]{%d})' % nargs if option else '((?:-*A){%d}-*)' % nargs
23842381
23852382 # return the pattern
23862383 return nargs_pattern
@@ -2483,21 +2480,17 @@ def _get_values(self, action, arg_strings):
24832480 value = action .const
24842481 else :
24852482 value = action .default
2486- if isinstance (value , str ):
2483+ if isinstance (value , str ) and value is not SUPPRESS :
24872484 value = self ._get_value (action , value )
2488- self ._check_value (action , value )
24892485
24902486 # when nargs='*' on a positional, if there were no command-line
24912487 # args, use the default if it is anything other than None
24922488 elif (not arg_strings and action .nargs == ZERO_OR_MORE and
24932489 not action .option_strings ):
24942490 if action .default is not None :
24952491 value = action .default
2496- self ._check_value (action , value )
24972492 else :
2498- # since arg_strings is always [] at this point
2499- # there is no need to use self._check_value(action, value)
2500- value = arg_strings
2493+ value = []
25012494
25022495 # single argument or optional argument produces a single value
25032496 elif len (arg_strings ) == 1 and action .nargs in [None , OPTIONAL ]:
@@ -2554,11 +2547,15 @@ def _get_value(self, action, arg_string):
25542547
25552548 def _check_value (self , action , value ):
25562549 # converted value must be one of the choices (if specified)
2557- if action .choices is not None and value not in action .choices :
2558- args = {'value' : value ,
2559- 'choices' : ', ' .join (map (repr , action .choices ))}
2560- msg = _ ('invalid choice: %(value)r (choose from %(choices)s)' )
2561- raise ArgumentError (action , msg % args )
2550+ choices = action .choices
2551+ if choices is not None :
2552+ if isinstance (choices , str ):
2553+ choices = iter (choices )
2554+ if value not in choices :
2555+ args = {'value' : value ,
2556+ 'choices' : ', ' .join (map (repr , action .choices ))}
2557+ msg = _ ('invalid choice: %(value)r (choose from %(choices)s)' )
2558+ raise ArgumentError (action , msg % args )
25622559
25632560 # =======================
25642561 # Help-formatting methods
0 commit comments