changeset: 71898:148c84b766e8 branch: 2.7 tag: tip parent: 71890:b4ccf8e1fdba user: Arnaud Fontaine date: Thu Aug 18 17:12:32 2011 +0900 summary: #12776: call argparse type function (specified by add_argument) only once. diff -r b4ccf8e1fdba -r 148c84b766e8 Lib/argparse.py --- a/Lib/argparse.py Tue Aug 16 22:26:48 2011 -0500 +++ b/Lib/argparse.py Thu Aug 18 17:12:32 2011 +0900 @@ -1705,10 +1705,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, basestring): - 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: @@ -1936,12 +1933,23 @@ if positionals: self.error(_('too few arguments')) - # make sure all required actions were present + # make sure all required actions were present and also convert + # action defaults which were not given as arguments for action in self._actions: - if action.required: - if action not in seen_actions: + if action not in seen_actions: + if action.required: name = _get_action_name(action) self.error(_('argument %s is required') % name) + 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, basestring) and \ + action.default == getattr(namespace, action.dest): + setattr(namespace, action.dest, + self._get_value(action, action.default)) # make sure all required groups had one option present for group in self._mutually_exclusive_groups: diff -r b4ccf8e1fdba -r 148c84b766e8 Lib/test/test_argparse.py --- a/Lib/test/test_argparse.py Tue Aug 16 22:26:48 2011 -0500 +++ b/Lib/test/test_argparse.py Thu Aug 18 17:12:32 2011 +0900 @@ -4414,6 +4414,22 @@ else: self.fail() +# ================================================ +# 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 # ======================