From eaae1b76aecd2c2fc1cf1aa1578db69e7d1464e6 Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Wed, 12 Sep 2012 14:34:50 -0400 Subject: [PATCH 1/2] A follow up for issue #15906: change the test for calling the type conversion on the action's default, reverting it back to previous behavior. Conversion is only done on string defaults. Add a test for this and another test that ensures such type conversions are only called once. --- Lib/argparse.py | 2 +- Lib/test/test_argparse.py | 31 +++++++++++++++++++++++++++---- 2 files changed, 28 insertions(+), 5 deletions(-) diff --git a/Lib/argparse.py b/Lib/argparse.py index fba6a262f52..e2677f81d69 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1957,7 +1957,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and - isinstance(action, _StoreAction) and + isinstance(action.default, basestring) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest, diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index cd80dc6d16f..22c26cc1038 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -4500,11 +4500,11 @@ class TestTypeFunctionCallOnlyOnce(TestCase): args = parser.parse_args('--foo spam!'.split()) self.assertEqual(NS(foo='foo_converted'), args) -# ================================================================ -# Check that the type function is called with a non-string default -# ================================================================ +# ================================================================== +# Check semantics regarding the default argument and type conversion +# ================================================================== -class TestTypeFunctionCallWithNonStringDefault(TestCase): +class TestTypeFunctionCalledOnDefault(TestCase): def test_type_function_call_with_non_string_default(self): def spam(int_to_convert): @@ -4514,8 +4514,31 @@ class TestTypeFunctionCallWithNonStringDefault(TestCase): parser = argparse.ArgumentParser() parser.add_argument('--foo', type=spam, default=0) args = parser.parse_args([]) + # foo should *not* be converted because its default is not a string. + self.assertEqual(NS(foo=0), args) + + def test_type_function_call_with_string_default(self): + def spam(int_to_convert): + return 'foo_converted' + + parser = argparse.ArgumentParser() + parser.add_argument('--foo', type=spam, default='0') + args = parser.parse_args([]) + # foo is converted because its default is a string. self.assertEqual(NS(foo='foo_converted'), args) + def test_no_double_type_conversion_of_default(self): + def extend(str_to_convert): + return str_to_convert + '*' + + parser = argparse.ArgumentParser() + parser.add_argument('--test', type=extend, default='*') + args = parser.parse_args([]) + # The test argument will be two stars, one coming from the default + # value and one coming from the type conversion being called exactly + # once. + self.assertEqual(NS(test='**'), args) + def test_issue_15906(self): # Issue #15906: When action='append', type=str, default=[] are # providing, the dest value was the string representation "[]" when it From 2dceb359cb0353d4f327fc36be27e67a3e94566e Mon Sep 17 00:00:00 2001 From: Barry Warsaw Date: Wed, 12 Sep 2012 14:42:34 -0400 Subject: [PATCH 2/2] Update merge from 2.7: s/basetring/str --- Lib/argparse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/argparse.py b/Lib/argparse.py index e2677f81d69..eb894caebc2 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -1957,7 +1957,7 @@ class ArgumentParser(_AttributeHolder, _ActionsContainer): # twice (which may fail) if the argument was given, but # only if it was defined already in the namespace if (action.default is not None and - isinstance(action.default, basestring) and + isinstance(action.default, str) and hasattr(namespace, action.dest) and action.default is getattr(namespace, action.dest)): setattr(namespace, action.dest,