2

I need to implement a command line for which there are several ways of using a sub-command.

Example:

For this simple "git merge", there are 2 ways of using it, that are mutually exclusive.

1) git merge (--continue | --abort | --quit)
2) git merge [--no-commit] [-m <msg>] [<commit>​]

My question is:

Using argparse, how to implement a parser for this simple example?

I used:

  • "add_subparsers" to create the merge sub-command.
  • "add_mutually_exclusive_group" to represent "(--continue | --abort | --quit)".
  • "add_argument_group" to resesent the second way of using.

Here is my code:

# Template command
parser_template = subparsers.add_parser('merge')

groupA = parser_template.add_argument_group('When merge is on-going')
excl_group = groupA.add_mutually_exclusive_group(required=True)
excl_group.add_argument('--continue', action='store_true')
excl_group.add_argument('--abort', action='store_true')
excl_group.add_argument('--quit', action='store_true')

groupB = parser_template.add_argument_group('Start a merge')
groupB.add_argument('--no-commit', action='store_true')
groupB.add_argument('-m', metavar='<msg>')
groupB.add_argument('commit', metavar='<commit>')

The help message is:

(venv) >> git merge -h
usage: git merge [-h] [--no-commit] [-m <msg>]
                 (--continue | --abort | --quit)
                 <commit>

optional arguments:
  -h, --help   show this help message and exit

When merge is on-going:
  --continue
  --abort
  --quit

Start a merge:
  --no-commit
  -m <msg>
  <commit>

However, groupA and groupB are not yet mutually exclusive among themselves. We can see it from the "usage" part, and this command works while it is non-sense:

(venv) >> git merge --no-commit --continue 34567

How groupA and groupB can become mutually exclusive ?

Finally, if argparse is not able, does another library exist with this functionality?

Thanks for any help.

  • `argument_group` is just a help tool, not a parsing one. There isn't a group nesting or extended logic. But in many cases you can do the same testing after parsing. Beware that as written `commit` is a required positional. How about splitting the `merge` subcommand into two? – hpaulj Sep 28 '19 at 16:38
  • Thank you @hpaulj, you have right and I found duplicates. I edited my question here above. – Adrien Faucon Sep 29 '19 at 07:06

1 Answers1

0

Found 2 duplicates:

Summary: It is not possible for the moment. To get around, one possibility if to check the arguments manually after parsing, or to split the sub-command into 2 different sub-commands.

An issue has been opened: https://bugs.python.org/issue11588