Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Group in a group ArgParse

So I'm using argparse and I'm trying to create something that I can't seem to find the solution anywhere.

I'm trying to do [A | [B C]]. So either I have A or (B and C).

EDIT So some example of code would be

parser = argparse.ArgumentParser()
group = parser.add_mutually_exclusive_group(required=False)
group.add_argument("-a")
more = group.add_mutually_exclusive_group()
more.add_argument("-b")
more.add_argument("c")

This however ends up giving me [A | [B | C]]

like image 620
Harbus Avatar asked May 18 '16 23:05

Harbus


2 Answers

import argparse

parser = argparse.ArgumentParser(description='test group')
subparsers = parser.add_subparsers(help='sub-commands help')
sp = subparsers.add_parser('A', help='A command')
sp.set_defaults(cmd = 'A')
sp = subparsers.add_parser('B', help='B command')
sp.set_defaults(cmd = 'B')
sp.add_argument('C', help='C option')

args = parser.parse_args()

if (args.cmd == 'A'):
    print("running A mode")
else:
    print("running B mode with C=%s" % args.C)

Here's execution log:

$ python test.py A
running A mode
$ python test.py B
usage: test.py B [-h] C
$ python test.py B some
running B mode with C=some

Mutually exclusive groups are intended for cases when user have to select at least one option out of a given set, or if required=True exactly one option.

like image 73
user3159253 Avatar answered Oct 13 '22 01:10

user3159253


The mutually exclusive group mechanism is just for a simple (flat) exclusive or group. There's no mechanism for nesting one group in another, or for applying other logic (and, any etc).

You need to do your own testing after parsing. As long as the defaults are reasonable (e.g. the default default None) that isn't hard.

Subparsers provide another kind of grouping logic, which may work for you.

This has been raised in other SO questions, and a Python bug/issue, if you need to explore it in more detail.

===============

argument groups, despite the name, do not work with mutually exclusive groups. Their intended purpose is entirely different (grouping of help lines). You can nest one mutually exclusive group within another, but the net effect is to put everything in one group.

argparse: some mutually exclusive arguments in required group

============================

import argparse

usage = '%(prog)s [A | [B ? C]]'
parser = argparse.ArgumentParser(usage=usage)
parser.add_argument('-a')
parser.add_argument('-b')
parser.add_argument('-c')
args=parser.parse_args()

print(args)
if args.a is not None:
   if not(args.b is None and args.c is None):
      parser.error('Cannot use b or c with a')

with resulting runs

1722:~/mypy$ python3 stack37311550.py -a 1
Namespace(a='1', b=None, c=None)
1726:~/mypy$ python3 stack37311550.py -a 1 -b2
Namespace(a='1', b='2', c=None)
usage: stack37311550.py [A | [B ? C]]
stack37311550.py: error: Cannot use b or c with a
1726:~/mypy$ python3 stack37311550.py -c3 -b2
Namespace(a=None, b='2', c='3')
1726:~/mypy$ python3 stack37311550.py -c3 -b2 -a1
Namespace(a='1', b='2', c='3')
usage: stack37311550.py [A | [B ? C]]
stack37311550.py: error: Cannot use b or c with a
like image 22
hpaulj Avatar answered Oct 12 '22 23:10

hpaulj