mardi 8 avril 2014

python - argparse - comportement de reproduction de "--aider" argument avec un argument spécifique - Stack Overflow


I have some trouble while working with the argparse module for Python v2.7. Basically, what I have is a script that works with 5 mandatory arguments :



  1. url

  2. method

  3. login

  4. password

  5. output


An example of the syntax would look like this :



script.py -w/--url [URL] -m/--method [METHOD] -l/--login [LOGIN] -p/--password [PASSWORD] -o/--output [OUTPUT]



What I'd like to do is this :



  • add an optional argument -t/--test

  • its behavior would be that, based on the url used with the -w/--url argument, it would bypass completely the -m/--method, -l/--login and -p/--password arguments but, for it to work, I need to tell argparse to stop processing arguments if -t/--test is provided (but only with -w/--url).


Is this behavior even possible? I tried to play with argparse sub-commands but it seems to be (at least to my small knowledge) a bit overkill.


NB: Here is my original code :


# Description : parses script arguments
# Argument(s) : all
# Return value : all arguments values
def testArgs():
parser = argparse.ArgumentParser(description='Foo', formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-w','--url', help='URL', required=True)
parser.add_argument('-t','--test', help='Test command', action='store_true')
parser.add_argument('-m','--method', help='METHOD', required=True)
parser.add_argument('-u','--login_name', help='LOGIN', required=True)
parser.add_argument('-p','--login_password', help='PASSWORD', required=True)
parser.add_argument('-o','--output_format', help='OUTPUT', required=True, choices=['json', 'yaml', 'python'], default='json')
args = parser.parse_args()
return args

EDIT : After a lot of testing, I have managed the following :


def testArgs():
parser = argparse.ArgumentParser(description='DESCRIPTION')
subparsers = parser.add_subparsers()
p_list = subparsers.add_parser('test', help='List all available methods')
p_list.add_argument('-w', help='URL', required=True)
p_list.add_argument('-t', help='Test', action='store_true', required=True)
p_cmd = subparsers.add_parser('cmd', help='Executes command')
p_cmd.add_argument('-w', help='URL', required=True)
p_cmd.add_argument('-m', help='Method', required=True)
p_cmd.add_argument('-l', help='Login', required=True)
p_cmd.add_argument('-p', help='Password', required=True)
p_cmd.add_argument('-o', help='Output', required=True)
args = parser.parse_args()
return args

Which exhibits the following behavior :


$ python testArgparse.py -h
usage: testArgeparse.py [-h] {test,cmd} ...

DESCRIPTION

positional arguments:
{test,cmd}
test Lists all available methods
cmd Executes command

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

But to access help on the others arguments, I need to do the following :


$ python testArgparse.py test -h
usage: testArgparse.py test [-h] -w W -t

optional arguments:
-h, --help show this help message and exit
-w W URL
-t Test


$ python testArgparse.py cmd -h
usage: testArgparse.py cmd [-h] -w W -m M -l L -p P -o O

optional arguments:
-h, --help show this help message and exit
-w W URL
-m M Method
-l L Login
-p P Password
-o O Output

I'd like to be able to, at least, display help about all arguments without having to use --help for both test and cmd arguments.


Ideally, what I'd like is this behavior :


$ python testArgparse.py [-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]



required=True with store_true does not make sense. The default is False, but if it is required the returned value will always be True.


Since only -w is required unconditionally, I would drop the required parameter on everything else. Then test for the required values after parse_args. I can still issue an argparse error with usage at that time. In other words, do my own testing rather than try something fancy in argparse.


def testArgs():
usage = '[-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]'
parser = argparse.ArgumentParser(description='DESCRIPTION',usage=usage)
parser.add_argument('-w', help='URL', required=True)
parser.add_argument('-t', help='Test', action='store_true')
parser.add_argument('-m', help='Method')
parser.add_argument('-l', help='Login')
parser.add_argument('-p', help='Password')
parser.add_argument('-o', help='Output')
args = parser.parse_args()

# sample test, streamline and refine to suit your needs
# this assumes the default for all these args is None
if not args.t: # '-t' in in argv
if any([args.m is None, args.l is None, args.p is None, args.o is None]):
parser.error('m,l,p,o are all required')
return args

1216:~/mypy$ python2.7 stack21070971.py
usage: [-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]
stack21070971.py: error: argument -w is required

1213:~/mypy$ python2.7 stack21070971.py -w url
usage: [-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]
stack21070971.py: error: m,l,p,o are all required

1213:~/mypy$ python2.7 stack21070971.py -w url -t
Namespace(l=None, m=None, o=None, p=None, t=True, w='url')

1214:~/mypy$ python2.7 stack21070971.py -w url -m mmm
usage: [-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]
stack21070971.py: error: m,l,p,o are all required
...

1215:~/mypy$ python2.7 stack21070971.py -w url -m mmm -l uuu -p ppp -o ooo
Namespace(l='uuu', m='mmm', o='ooo', p='ppp', t=False, w='url')


I have some trouble while working with the argparse module for Python v2.7. Basically, what I have is a script that works with 5 mandatory arguments :



  1. url

  2. method

  3. login

  4. password

  5. output


An example of the syntax would look like this :



script.py -w/--url [URL] -m/--method [METHOD] -l/--login [LOGIN] -p/--password [PASSWORD] -o/--output [OUTPUT]



What I'd like to do is this :



  • add an optional argument -t/--test

  • its behavior would be that, based on the url used with the -w/--url argument, it would bypass completely the -m/--method, -l/--login and -p/--password arguments but, for it to work, I need to tell argparse to stop processing arguments if -t/--test is provided (but only with -w/--url).


Is this behavior even possible? I tried to play with argparse sub-commands but it seems to be (at least to my small knowledge) a bit overkill.


NB: Here is my original code :


# Description : parses script arguments
# Argument(s) : all
# Return value : all arguments values
def testArgs():
parser = argparse.ArgumentParser(description='Foo', formatter_class=argparse.RawDescriptionHelpFormatter)
parser.add_argument('-w','--url', help='URL', required=True)
parser.add_argument('-t','--test', help='Test command', action='store_true')
parser.add_argument('-m','--method', help='METHOD', required=True)
parser.add_argument('-u','--login_name', help='LOGIN', required=True)
parser.add_argument('-p','--login_password', help='PASSWORD', required=True)
parser.add_argument('-o','--output_format', help='OUTPUT', required=True, choices=['json', 'yaml', 'python'], default='json')
args = parser.parse_args()
return args

EDIT : After a lot of testing, I have managed the following :


def testArgs():
parser = argparse.ArgumentParser(description='DESCRIPTION')
subparsers = parser.add_subparsers()
p_list = subparsers.add_parser('test', help='List all available methods')
p_list.add_argument('-w', help='URL', required=True)
p_list.add_argument('-t', help='Test', action='store_true', required=True)
p_cmd = subparsers.add_parser('cmd', help='Executes command')
p_cmd.add_argument('-w', help='URL', required=True)
p_cmd.add_argument('-m', help='Method', required=True)
p_cmd.add_argument('-l', help='Login', required=True)
p_cmd.add_argument('-p', help='Password', required=True)
p_cmd.add_argument('-o', help='Output', required=True)
args = parser.parse_args()
return args

Which exhibits the following behavior :


$ python testArgparse.py -h
usage: testArgeparse.py [-h] {test,cmd} ...

DESCRIPTION

positional arguments:
{test,cmd}
test Lists all available methods
cmd Executes command

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

But to access help on the others arguments, I need to do the following :


$ python testArgparse.py test -h
usage: testArgparse.py test [-h] -w W -t

optional arguments:
-h, --help show this help message and exit
-w W URL
-t Test


$ python testArgparse.py cmd -h
usage: testArgparse.py cmd [-h] -w W -m M -l L -p P -o O

optional arguments:
-h, --help show this help message and exit
-w W URL
-m M Method
-l L Login
-p P Password
-o O Output

I'd like to be able to, at least, display help about all arguments without having to use --help for both test and cmd arguments.


Ideally, what I'd like is this behavior :


$ python testArgparse.py [-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]


required=True with store_true does not make sense. The default is False, but if it is required the returned value will always be True.


Since only -w is required unconditionally, I would drop the required parameter on everything else. Then test for the required values after parse_args. I can still issue an argparse error with usage at that time. In other words, do my own testing rather than try something fancy in argparse.


def testArgs():
usage = '[-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]'
parser = argparse.ArgumentParser(description='DESCRIPTION',usage=usage)
parser.add_argument('-w', help='URL', required=True)
parser.add_argument('-t', help='Test', action='store_true')
parser.add_argument('-m', help='Method')
parser.add_argument('-l', help='Login')
parser.add_argument('-p', help='Password')
parser.add_argument('-o', help='Output')
args = parser.parse_args()

# sample test, streamline and refine to suit your needs
# this assumes the default for all these args is None
if not args.t: # '-t' in in argv
if any([args.m is None, args.l is None, args.p is None, args.o is None]):
parser.error('m,l,p,o are all required')
return args

1216:~/mypy$ python2.7 stack21070971.py
usage: [-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]
stack21070971.py: error: argument -w is required

1213:~/mypy$ python2.7 stack21070971.py -w url
usage: [-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]
stack21070971.py: error: m,l,p,o are all required

1213:~/mypy$ python2.7 stack21070971.py -w url -t
Namespace(l=None, m=None, o=None, p=None, t=True, w='url')

1214:~/mypy$ python2.7 stack21070971.py -w url -m mmm
usage: [-w URL -t] | [-w URL -m METHOD -u LOGIN -p PASS -o OUTPUT]
stack21070971.py: error: m,l,p,o are all required
...

1215:~/mypy$ python2.7 stack21070971.py -w url -m mmm -l uuu -p ppp -o ooo
Namespace(l='uuu', m='mmm', o='ooo', p='ppp', t=False, w='url')

0 commentaires:

Enregistrer un commentaire