diff -r b5ccdf7c032a Doc/library/argparse.rst --- a/Doc/library/argparse.rst Sun Aug 21 00:39:18 2011 +0200 +++ b/Doc/library/argparse.rst Sun Aug 21 18:21:59 2011 +0200 @@ -1498,6 +1498,17 @@ >>> parser.parse_args(['co', 'bar']) Namespace(foo='bar') + Subparsers now support abbreviation when used. + So for example the following three calls all can be used + - as long as the choosen abbreviation is unambiguous: + + >>> parser.parse_args(['checkout', 'bar']) + Namespace(foo='bar') + >>> parser.parse_args(['check', 'bar']) + Namespace(foo='bar') + >>> parser.parse_args(['che', 'bar']) + Namespace(foo='bar') + One particularly effective way of handling sub-commands is to combine the use of the :meth:`add_subparsers` method with calls to :meth:`set_defaults` so that each subparser knows which Python function it should execute. For diff -r b5ccdf7c032a Lib/argparse.py --- a/Lib/argparse.py Sun Aug 21 00:39:18 2011 +0200 +++ b/Lib/argparse.py Sun Aug 21 18:21:59 2011 +0200 @@ -1108,14 +1108,18 @@ parser_name = values[0] arg_strings = values[1:] + # select the parser + parser = None + for p in self._name_parser_map: + if p.startswith(parser_name): + parser = self._name_parser_map[p] + break + # set the parser name if requested if self.dest is not SUPPRESS: - setattr(namespace, self.dest, parser_name) - - # select the parser - try: - parser = self._name_parser_map[parser_name] - except KeyError: + setattr(namespace, self.dest, p) + + if not parser: args = {'parser_name': parser_name, 'choices': ', '.join(self._name_parser_map)} msg = _('unknown parser %(parser_name)r (choices: %(choices)s)') % args @@ -2286,11 +2290,18 @@ def _check_value(self, action, value): # converted value must be one of the choices (if specified) - if action.choices is not None and value not in action.choices: - args = {'value': value, - 'choices': ', '.join(map(repr, action.choices))} - msg = _('invalid choice: %(value)r (choose from %(choices)s)') - raise ArgumentError(action, msg % args) + if action.choices is not None: + ac = [ax for ax in action.choices if str(ax).startswith(str(value))] + if len(ac) == 0: + args = {'value': value, + 'choices': ', '.join(map(repr, action.choices))} + msg = _('invalid choice: %(value)r (choose from %(choices)s)') + raise ArgumentError(action, msg % args) + elif len(ac) > 1: + args = {'value': value, + 'choices': ', '.join(ac)} + msg = _('ambiguous choice: %(value)r could match %(choices)s') + raise ArgumentError(action, msg % args) # ======================= # Help-formatting methods