changeset: 71898:91ec14d7dccc tag: tip user: Arnaud Fontaine date: Thu Aug 18 17:54:35 2011 +0900 summary: #12776: call argparse type function (specified by add_argument) only once. diff -r 50f1922bc1d5 -r 91ec14d7dccc Lib/argparse.py --- a/Lib/argparse.py Wed Aug 17 20:49:41 2011 +0200 +++ b/Lib/argparse.py Thu Aug 18 17:54:35 2011 +0900 @@ -1743,10 +1743,7 @@ if action.dest is not SUPPRESS: if not hasattr(namespace, action.dest): if action.default is not SUPPRESS: - default = action.default - if isinstance(action.default, str): - default = self._get_value(action, default) - setattr(namespace, action.dest, default) + setattr(namespace, action.dest, action.default) # add any parser defaults that aren't present for dest in self._defaults: @@ -1972,6 +1969,25 @@ # make sure all required actions were present required_actions = [_get_action_name(action) for action in self._actions if action.required and action not in seen_actions] + + # make sure all required actions were present and also convert + # action defaults which were not given as arguments + required_actions = [] + for action in self._actions: + if action not in seen_actions: + if action.required: + required_actions.append(_get_action_name(action)) + else: + # Convert action default now instead of doing it before + # parsing arguments to avoid calling convert functions + # twice (which may fail) if the argument was given, but + # only if it was defined already in the namespace + if hasattr(namespace, action.dest) and \ + isinstance(action.default, str) and \ + action.default == getattr(namespace, action.dest): + setattr(namespace, action.dest, + self._get_value(action, action.default)) + if required_actions: self.error(_('the following arguments are required: %s') % ', '.join(required_actions)) diff -r 50f1922bc1d5 -r 91ec14d7dccc Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py Wed Aug 17 20:49:41 2011 +0200 +++ b/Lib/test/test_argparse.py Thu Aug 18 17:54:35 2011 +0900 @@ -4541,6 +4541,22 @@ self.assertNotIn(msg, 'optional_positional') +# ================================================ +# Check that the type function is called only once +# ================================================ + +class TestTypeFunctionCallOnlyOnce(TestCase): + + def test_type_function_call_only_once(self): + def spam(string_to_convert): + self.assertEqual(string_to_convert, 'spam!') + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default='bar') + args = parser.parse_args(['--foo', 'spam!']) + self.assertEqual(NS(foo='foo_converted'), args) + # ====================== # parse_known_args tests # ======================