Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

argparse help error: arguments created by add_mutually_exclusive_group() are shown outside their parent group created by add_argument_group() #70070

Open
balage mannequin opened this issue Dec 16, 2015 · 7 comments
Labels
stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error

Comments

@balage
Copy link
Mannequin

balage mannequin commented Dec 16, 2015

BPO 25882
Files
  • issue25882.py
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = None
    closed_at = None
    created_at = <Date 2015-12-16.13:14:43.143>
    labels = ['type-bug']
    title = 'argparse help error: arguments created by add_mutually_exclusive_group() are shown outside their parent group created by add_argument_group()'
    updated_at = <Date 2017-02-26.18:04:42.671>
    user = 'https://bugs.python.org/balage'

    bugs.python.org fields:

    activity = <Date 2017-02-26.18:04:42.671>
    actor = 'paul.j3'
    assignee = 'none'
    closed = False
    closed_date = None
    closer = None
    components = []
    creation = <Date 2015-12-16.13:14:43.143>
    creator = 'balage'
    dependencies = []
    files = ['41332']
    hgrepos = []
    issue_num = 25882
    keywords = []
    message_count = 7.0
    messages = ['256518', '256569', '256573', '256597', '256598', '256612', '288606']
    nosy_count = 3.0
    nosy_names = ['paul.j3', 'srikanth', 'balage']
    pr_nums = []
    priority = 'normal'
    resolution = None
    stage = None
    status = 'open'
    superseder = None
    type = 'behavior'
    url = 'https://bugs.python.org/issue25882'
    versions = ['Python 2.7']

    @balage
    Copy link
    Mannequin Author

    balage mannequin commented Dec 16, 2015

    So, a parent parser is created. It has a "global arguments" group (by add_argument_group()) and this group has a mutually exclusive group. Then a child parser is created used previous parser as parent.
    The error: in the child parser help: the arguments of the mutually exclusive group are printed into the part of child parser instead of their "global arguments" group.

    The next code shows the problem:

    import argparse
    # create parent parser
    parent_parser = argparse.ArgumentParser(add_help = False)
    # create group for its arguments
    global_group = parent_parser.add_argument_group("global arguments")
    global_group.add_argument("--global-arg1")
    global_group.add_argument("--global-arg2")
    mutex_group = global_group.add_mutually_exclusive_group()
    mutex_group.add_argument("--mutex-arg1")
    mutex_group.add_argument("--mutex-arg2")
    # create child parser
    child_parser = argparse.ArgumentParser(parents = [parent_parser])
    child_parser.add_argument("--child-arg1")
    child_parser.add_argument("--child-arg2")
    print("="*100)
    parent_parser.print_help()
    print("="*100)
    child_parser.print_help()

    The output:

    ====================================================================================================
    usage: test.py [--global-arg1 GLOBAL_ARG1] [--global-arg2 GLOBAL_ARG2]
    [--mutex-arg1 MUTEX_ARG1 | --mutex-arg2 MUTEX_ARG2]

    global arguments:
    --global-arg1 GLOBAL_ARG1
    --global-arg2 GLOBAL_ARG2
    --mutex-arg1 MUTEX_ARG1
    --mutex-arg2 MUTEX_ARG2
    ====================================================================================================
    usage: test.py [-h] [--global-arg1 GLOBAL_ARG1] [--global-arg2 GLOBAL_ARG2]
    [--mutex-arg1 MUTEX_ARG1 | --mutex-arg2 MUTEX_ARG2]
    [--child-arg1 CHILD_ARG1] [--child-arg2 CHILD_ARG2]

    optional arguments:
    -h, --help show this help message and exit
    --mutex-arg1 MUTEX_ARG1
    --mutex-arg2 MUTEX_ARG2
    --child-arg1 CHILD_ARG1
    --child-arg2 CHILD_ARG2

    global arguments:
    --global-arg1 GLOBAL_ARG1
    --global-arg2 GLOBAL_ARG2

    The error is that the --mutex-arg-s can be seen in "optional arguments" part instead of "global arguments" part in the second (child help) case.
    In the first (parent help) case the --mutex-arg-s are printed into the good section.

    @balage balage mannequin added the type-bug An unexpected behavior, bug, or error label Dec 16, 2015
    @paulj3
    Copy link
    Mannequin

    paulj3 mannequin commented Dec 17, 2015

    In

    _ActionsContainer._add_container_actions there is this note:

    # add container's mutually exclusive groups
    # NOTE: if add_mutually_exclusive_group ever gains title= and
    # description= then this code will need to be expanded as above
    

    In other bug/issues we've noted that the way to give an exclusive group a title and description is to nest it in an argument_group.

    So it looks like no one has worked through the details - in this parent situation - of adding a nested mutually exclusive group.

    In my preliminary tests, it looks like the 'group_map' is being messed up by the block of code that adds the mutually_exclusive_groups. I don't know how easy it is to fix that.

    The immediate user solution is not use parents and nested mutually exclusive groups together.

    @paulj3
    Copy link
    Mannequin

    paulj3 mannequin commented Dec 17, 2015

    I've attached a file that monkey patches the _ActionsContainer._add_container_actions method.

    It corrects the _container attribute of the copied mutually exclusive groups. I've only tested it for the case presented in this issue (and the relate Stackoverflow question).

    I may construct of formal patch later.

    @balage
    Copy link
    Mannequin Author

    balage mannequin commented Dec 17, 2015

    paul.j3, thx the the patch, it is perfect!!!

    @balage
    Copy link
    Mannequin Author

    balage mannequin commented Dec 17, 2015

    Unfortunately the problem consists in case of normal sub-group too :(.

    If you complete my previous example code with the next code, then the problem can be seen:

    sub_group = global_group.add_argument_group()
    sub_group.add_argument("--sub-arg1")
    sub_group.add_argument("--sub-arg2")

    Part of unexpected output:

    optional arguments:
    -h, --help show this help message and exit
    --sub-arg1 SUB_ARG1
    --sub-arg2 SUB_ARG2
    --child-arg1 CHILD_ARG1
    --child-arg2 CHILD_ARG2

    Is there a patch for it too? :)

    @paulj3
    Copy link
    Mannequin

    paulj3 mannequin commented Dec 17, 2015

    Argument groups are not designed to be nested.

    If you print_help the parent parser, you'll see that the sub_args are missing entirely, not just displaced. They appear in the usage, but not the help lines. sub_group has no record that it was added to global_group (it doesn't have the ._container attribute).

    All containers, both parsers and groups, have a ._action_groups list (inherited from their common super), but I don't think any of the group code uses that list. And the part of the help_formatter than handles groups is not recursive. It handles just one level of groups.

    I suspect the sub_group actions appear in the 'optional arguments' group for similar reasons as with the mutually_exclusive_group, but the details probably differ.

    There have been a number of questions on SO about using argument_groups to add actions to a mutually_exclusive_group. They either want a convenient way of adding a group of actions, or they want some sort of 'any' logic applied to the subgroup. We've had to say - no you can't nest groups like that. I have explored in another bug/issue the idea of nesting groups and applying all sorts of logic (not just xor), but that's a big issue.

    @paulj3
    Copy link
    Mannequin

    paulj3 mannequin commented Feb 26, 2017

    Earlier issue on the same topic - passing a mutually exclusive group via parents

    http://bugs.python.org/issue16807

    Can they be consolidated?

    @ezio-melotti ezio-melotti transferred this issue from another repository Apr 10, 2022
    @iritkatriel iritkatriel added the stdlib Python modules in the Lib dir label Nov 23, 2023
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    stdlib Python modules in the Lib dir type-bug An unexpected behavior, bug, or error
    Projects
    Status: Bugs
    Development

    No branches or pull requests

    1 participant