Feature or enhancement
Proposal:
Summary
We add the keyword-only flag subnamespace to _SubParsersAction.add_parser(), which when set to True tells the parent parser to store the subparser's parsed arguments contained in their own Namespace, nested within the parent's Namespace.
This allows hierarchical nested Namespaces to form when calling parser.parse_args(), which mirror the hierarchical nature of nested subparsers.
This also solves the problem of parsers and their subparsers having conflicting dest parameters which are subject to shadowing / conflict resolution. This has been a long standing issue for argparse #59633
By default subnamespace is False for backwards compatibility, making this feature opt-in.
Mini Example
Taken from the [implementation tests][tests]
import argparse
inet = argparse.ArgumentParser(add_help=False)
inet.add_argument("address")
inet.add_argument("port", type=int)
inet.add_argument("--use-proxy", action="store_true")
unix = argparse.ArgumentParser(add_help=False)
unix.add_argument("path")
parser = argparse.ArgumentParser(prog="my-socat")
parser.add_argument("--key-file")
action = parser.add_subparsers(required=True, dest="action")
parser_bind = action.add_parser("bind", subnamespace=True)
parser_bind.add_argument("--fork", action="store_true")
bind_family = parser_bind.add_subparsers(required=True, dest="family")
parser_bind_inet = bind_family.add_parser("inet", subnamespace=True, parents=[inet])
parser_bind_unix = bind_family.add_parser("unix", subnamespace=True, parents=[unix])
parser_connect = action.add_parser("connect", subnamespace=True)
connect_family = parser_connect.add_subparsers(required=True, dest="family")
parser_connect_inet = connect_family.add_parser("inet", subnamespace=True, parents=[inet])
parser_connect_unix = connect_family.add_parser("unix", subnamespace=True, parents=[unix])
args = parser.parse_args(["bind", "unix", "/foo/bar/socket"])
assert args == argparse.Namespace(
key_file=None,
action="bind",
bind=argparse.Namespace(
fork=False,
family="unix",
unix=argparse.Namespace(
path="/foo/bar/socket"
)
)
)
assert args.bind.unix.path == "/foo/bar/socket"
Closes / supersedes #59633 #103639 #103640
Implementation PR incoming
Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
Full discussion thread and rationale: https://discuss.python.org/t/107202
Linked PRs
Feature or enhancement
Proposal:
Summary
We add the keyword-only flag
subnamespaceto_SubParsersAction.add_parser(), which when set toTruetells the parent parser to store the subparser's parsed arguments contained in their ownNamespace, nested within the parent'sNamespace.This allows hierarchical nested
Namespaces to form when callingparser.parse_args(), which mirror the hierarchical nature of nested subparsers.This also solves the problem of parsers and their subparsers having conflicting
destparameters which are subject to shadowing / conflict resolution. This has been a long standing issue for argparse #59633By default
subnamespaceisFalsefor backwards compatibility, making this feature opt-in.Mini Example
Taken from the [implementation tests][tests]
Closes / supersedes #59633 #103639 #103640
Implementation PR incoming
Has this already been discussed elsewhere?
I have already discussed this feature proposal on Discourse
Links to previous discussion of this feature:
Full discussion thread and rationale: https://discuss.python.org/t/107202
Linked PRs
subnamespacefeature #149462