[argparse] mutually exclusive group with 2 sets of options

  • Thread starter Francois Lafont
  • Start date
F

Francois Lafont

Hi,

Is it possible with argparse to have this syntax for a script?

my-script (-a -b VALUE-B | -c -d VALUE-D)

I would like to do this with the argparse module.

Thanks in advance.
 
F

Francois Lafont

Hello,

Up. ;-)

Le 04/08/2013 04:10, Francois Lafont a écrit :
Is it possible with argparse to have this syntax for a script?

my-script (-a -b VALUE-B | -c -d VALUE-D)

I would like to do this with the argparse module.

Thanks in advance.

I have found this post:
https://groups.google.com/forum/#!s...usive/argparse-users/-o6GOwhCjbQ/m-PfL4OxLAIJ

It was in 2011 and at that time, it was impossible to have the syntax above. I have the impression that it's impossible now yet. Am I wrong?

If it's impossible yet, I could try a hack. With some checks, I think I could have the "(-a -b VALUE-B | -c -d VALUE-D)" behavior but I would like this syntax appear in the help output too and I have no idea to do it.
 
J

Joshua Landau

Hello,

Up. ;-)

Le 04/08/2013 04:10, Francois Lafont a écrit :


I have found this post:

https://groups.google.com/forum/#!s...usive/argparse-users/-o6GOwhCjbQ/m-PfL4OxLAIJ

It was in 2011 and at that time, it was impossible to have the syntax
above. I have the impression that it's impossible now yet. Am I wrong?

If it's impossible yet, I could try a hack. With some checks, I think I
could have the "(-a -b VALUE-B | -c -d VALUE-D)" behavior but I would like
this syntax appear in the help output too and I have no idea to do it.


If possible you could try docopt. That should be able to do it quite easily..

You could write literally:

My-Script

Usage:
my-script (-a -b VALUE-B | -c -d VALUE-D)

Options:
-b VALUE-B Description
-d VALUE-D Description

as the grammar, but:

My-Script

Usage:
my-script -a -b VALUE-B
my-script -c -d VALUE-D

Options:
-b VALUE-B Description
-d VALUE-D Description

would be preferred.
 
J

Joseph L. Casale

You can probably do something similar using sub commands

The problem here is that argparse does not pass the subparser into the
parsed args and shared args between subparsers need to be declared
each time. Come execution time, when you have shared args you end
up testing for various incantations of the invoked code, you're better
off omitting subparsers and performing conditional tests after parsing
for incompatible combinations.

It's a waste of typing to write out a mode followed by params to achieve
the ops goal, I've hit the same limitation. Certainly a weakness of argparse
in my opinion. It's also a tough sell to force a user to install a package just
for the cli if you go with docopt. I'd love to see argparse expand or docopt
get included...

jlc
 
F

Francois Lafont

Le 05/08/2013 16:11, Miki Tebeka a écrit :
You can probably do something similar using sub commands (http://docs.python.org/2/library/argparse.html#sub-commands).

Yes, but this is not the same syntax. I want this syntax :

my-script (-a -b VALUE-B | -c -d VALUE-D)

I don't want this syntax:

my-script (subcommad-a -b VALUE-B | subcommand-c -d VALUE-D)

In fact, in this post, I have simplified my question to put the stress just on my problem. In the real life, my script already uses the subcommands (and no problem with that). But I need to have mutually exclusive groups with 2 *sets* of options for compatibility reasons with another programs.
 
J

Joseph L. Casale

I think you are looking for exclusive groups:

No. That links first doc line in that method shows the very point we are all discussing:

"Create a mutually exclusive group. argparse will make sure that only one
of the arguments in the mutually exclusive group was present on the
command line:"

Op requires more than one per group, this method "make sure that only one
of the arguments" is accepted.

jlc
 
F

Francois Lafont

Le 05/08/2013 22:01, Rafael Durán Castañeda a écrit :

Yes... but no. The doc explains you can do this:

my-script (-b VALUE-B | -d VALUE-D)

ie mutally exclusive group with *just* *one* option incompatible with another one.

But, apparently, you can't do that:

my-script (-a -b VALUE-B | -c -d VALUE-D)

ie mutually exclusive group with one *set* of option*s* incompatible with another *set* of option*s*. This is why I have posted my message. I have read the documentation before to post it. ;-)

I know docopt but I prefer argparse. My script have subcommands and some of them have common options, so I appreciate the parser objects and the inheritance between parser objects (with parents parameter of argparse.ArgumentParser class).
 
F

Francois Lafont

Hi,

On relfection, it's clear that:

1. the "(-a -b VALUE-B | -c -d VALUE-D)" syntax is not
implemented by the argparse module;

2. and get this syntax with "argparse + hacking" is not very clean.

So, finally I'll use the docopt module version 0.6.1.
For the inheritance of common options, I'll used something like
that (even if I prefer the oriented object side of the argparse
module):



[the main file]
#-----------------------------------
import importlib
import sys
from docopt import docopt

help_message ="""
Usage:
my-script (-h | --help)
my-script <command> [<args>...]

Options:
-h, --help
Show this help message and exit.

Available commands:
command1 Description1...
command2 Description2...

See 'my-script <command> -h' for more information on a specific command.
"""

if __name__ == '__main__':

args = docopt(help_message, options_first=True)
command = args['<command>']

try:
m = importlib.import_module('mymodule.' + command)
except ImportError:
print("Sorry, the %s command doesn't exist. See 'my-script -h'.") % (command,)
sys.exit(1)

args = docopt(m.help_message, options_first=False)
m.run(args)
#-----------------------------------



[a file for each specific command, mymodule/command1.py etc.]
#-----------------------------------
import mymodule.common as common

help_message = """
Usage:
my-script subcommand1 (-h | --help)
my-script subcommand1 %s -w <warning> -c <critical>

Options:
%s
-w <warning>, --warning=<warning>
Some help.
-c <critical>, --critical=<critical>
Some help.
""" % (common.common_syntax, common.common_help,)


def run(args):
pass
#-----------------------------------



[and a file for the common syntax, mymodule/common.py]
#-----------------------------------
common_syntax = """-H <host-address> -t <timeout>
(--v2c -C <community> | -l <login> -x <passwd> -X <privpass> -L <protocols>)"""

common_help = """ -h, --help
Show this help message and exit.
-H <host-address>, --host=<host-address>
Some help.
-t <timeout>, --timeout=<timeout>
Some help.
--v2c
Some help.
-C <community>, --community=<community>
Set the community password for SNMP V2c.
# etc.
# etc.
"""
#-----------------------------------

Thank you all.
 
F

Francois Lafont

Le 07/08/2013 01:18, Francois Lafont a écrit :
For the inheritance of common options, I'll used something like
that (even if I prefer the oriented object side of the argparse
module):

But I admit that this is a very simple and intelligent module. ;-)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top