#9351: set_defaults on subparser is no longer ignored if set on parent.

Before, if a default was set on the parent parser, any default for that
variable set via set_defaults on a subparser would be ignored.  Now
the subparser set_defaults is honored.

Patch by Jyrki Pullianinen.
This commit is contained in:
R David Murray 2014-10-17 19:55:11 -04:00
parent 685b3495e1
commit 7570cbdc6b
3 changed files with 18 additions and 1 deletions

View File

@ -1122,7 +1122,14 @@ class _SubParsersAction(Action):
# parse all the remaining options into the namespace
# store any unrecognized options on the object, so that the top
# level parser can decide what to do with them
namespace, arg_strings = parser.parse_known_args(arg_strings, namespace)
# In case this subparser defines new defaults, we parse them
# in a new namespace object and then update the original
# namespace for the relevant parts.
subnamespace, arg_strings = parser.parse_known_args(arg_strings, None)
for key, value in vars(subnamespace).items():
setattr(namespace, key, value)
if arg_strings:
vars(namespace).setdefault(_UNRECOGNIZED_ARGS_ATTR, [])
getattr(namespace, _UNRECOGNIZED_ARGS_ATTR).extend(arg_strings)

View File

@ -2795,6 +2795,13 @@ class TestSetDefaults(TestCase):
parser = ErrorRaisingArgumentParser(parents=[parent])
self.assertEqual(NS(x='foo'), parser.parse_args([]))
def test_set_defaults_on_parent_and_subparser(self):
parser = argparse.ArgumentParser()
xparser = parser.add_subparsers().add_parser('X')
parser.set_defaults(foo=1)
xparser.set_defaults(foo=2)
self.assertEqual(NS(foo=2), parser.parse_args(['X']))
def test_set_defaults_same_as_add_argument(self):
parser = ErrorRaisingArgumentParser()
parser.set_defaults(w='W', x='X', y='Y', z='Z')

View File

@ -33,6 +33,9 @@ Core and Builtins
Library
-------
- Issue #9351: Defaults set with set_defaults on an argparse subparser
are no longer ignored when also set on the parent parser.
- Issue #21991: Make email.headerregistry's header 'params' attributes
be read-only (MappingProxyType). Previously the dictionary was modifiable
but a new one was created on each access of the attribute.