Behaviour of the docopt module (argument parser) - python

I currently use the docopt lib for the first time so I surely do something wrong
My script is :
"""prog
Usage:
prog.py (-h | --help)
prog.py (--version)
prog.py -s TAG [-t NB_NUC]
Options:
-h, --help help
--version version
-s TAG Some TAG I want.
-t NB_NUC A number of nuc.
"""
If I write:
python prog.py -s SMT
I get:
{'--help': False,
'--version': False,
'-h': False,
'-s': True,
'-t': True,
'NB_NUC': None,
'TAG': 'SMT'}
And it seems to be correct, but if I write :
python prog.py -s -t 10 -> TAG contain 10 (instead of None)
python prog.py -t 10 -s SMT -> TAG contain always 10 (instead of SMT) and NB_NUC contain SMT (instead of 10)
python prog.py -s SMT -t -> TAG contain SMT and NB_NUC contain None (and its what I expected on this way)
So, I tried lot a combination, but I don't understand how this is supposed to word...
What I want is TAG always contains the values which correspond with the -s argument, with None or an error if nothing is given after -s, and I don't understand why it's not the case..
Thanks for your help !

Your are almost there, just need the "<...>" around the arguments:
"""prog
Usage:
prog.py (-h | --help)
prog.py (--version)
prog.py -s TAG [-t NB_NUC]
Options:
-h, --help help
--version version
-s TAG Some TAG I want.
-t NB_NUC A number of nuc.
"""

The problem came from the fact that previous version of docopt didn't work with tabulated indentation.
Actual version does, and the PEP8 recommend usage of spaces anyway.
And for the formating the easiest way is to only write
Usage:
prog.py (-h | --help)
prog.py (-v | --version)
prog.py [options] <mandatory_file>
And to put the differents options and their descriptions in the Options part.

Related

git subcommand with --help arg, not working

Having this example code:
#!/usr/bin/env python3
import argparse
def main():
parser = argparse.ArgumentParser(description="Some Description")
parser.add_argument('some-arg')
args = parser.parse_args()
print(args)
if __name__ == '__main__':
main()
I add this code to file called git-mycommand, made it executable and copied it to /usr/bin.
Now trying to run command with --help, gives me this unintended output:
user#user:~$ git mycommand --help
No manual entry for git-mycommand
See 'man 7 undocumented' for help when manual pages are not available.
If I run command normally without --help, It works properly, like:
oerp#oerp:~$ git mycommand some_val
Namespace(**{'some-arg': 'some_val'})
Or if I dont use it as git subcommand and run it directly, like:
oerp#oerp:~$ git-mycommand --help
usage: git-mycommand [-h] some-arg
Some Description
positional arguments:
some-arg
optional arguments:
-h, --help show this help message and exit
Does anyone know why custom git subcommand does not work properly with --help argument? Or maybe there is something else, I need to do, so it would show intended output?
The git command is receiving the --help option, not your subcommand.
Note that git --help ... is identical to git help ... because the former is internally converted into the latter.
https://git-scm.com/docs/git-help
git help invokes git-help which opens the man page for the given command.

Pass output of 'find' command to Python with docopt (issue with spaces)

Consider this simple Python command-line script:
"""foobar
Description
Usage:
foobar [options] <files>...
Arguments:
<files> List of files.
Options:
-h, --help Show help.
--version Show version.
"""
import docopt
args = docopt.docopt(__doc__)
print(args['<files>'])
And consider that I have the following files in a folder:
file1.pdf
file 2.pdf
Now I want to pass the output of the find command to my simple command-line script. But when I try
foobar `find . -iname '*.pdf'`
I don't get the list of files that I wanted, because the input is split on spaces. I.e. I get:
['./file', '2.pdf', './file1.pdf']
How can I correctly do this?
This isn't a Python question. This is all about how the shell tokenizes command lines. Whitespace is used to separate command arguments, which is why file 2.pdf is showing as as two separate arguments.
You can combine find and xargs to do what you want like this:
find . -iname '*.pdf' -print0 | xargs -0 foobar
The -print0 argument to find tells it to output filenames seperated by ASCII NUL characters rather than spaces, and the -0 argument to xargs tells it to expect that form of input. xargs with then call your foobar script with the correct arguments.
Compare:
$ ./foobar $(find . -iname '*.pdf' )
['./file', '2.pdf', './file1.pdf']
To:
$ find . -iname '*.pdf' -print0 | xargs -0 ./foobar
['./file 2.pdf', './file1.pdf']

Docopt extreemly unintuitive opions usage

Docopt loves to write lots of documentation, by I can't seem to find a single actual command line call inside their many pages of how to write the comments section. I have this very simple file:
"""Main.py
Usage:
main.py controller
main.py model
main.py form
main.py -h | --help
main.py --version
Options:
-h --help Show this screen.
--version Show version.
--outfile Output file.
"""
from docopt import docopt
if __name__ == '__main__':
arguments = docopt(__doc__, version='Main.py 1.0')
print(arguments)
I get the first part:
adams-mbp:Aut adam$ python main.py model
{'--help': 0,
'--outfile': None,
'--version': 0,
'Options:': False,
'Show': 0,
'controller': False,
'file.': False,
'form': False,
'model': True,
'screen.': False,
'this': False,
'version.': False}
But I can't seem to figure out how to pass an --outfile parameter. Here's what I've tried:
adams-mbp:Aut adam$ python main.py main.py --outfile thing
Usage:
main.py controller
main.py model
main.py form
main.py -h | --help
main.py --version
Options:
-h --help Show this screen.
--version Show version.
--outfile Output file.
adams-mbp:Aut adam$ python main.py main.py --outfile=thing
Usage:
main.py controller
main.py model
main.py form
main.py -h | --help
main.py --version
Options:
-h --help Show this screen.
--version Show version.
--outfile Output file.
adams-mbp:Aut adam$ python --outfile thing main.py main.py
Unknown option: --
usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.
adams-mbp:Aut adam$ python --outfile=thing main.py main.py
Unknown option: --
usage: python [option] ... [-c cmd | -m mod | file | -] [arg] ...
Try `python -h' for more information.
adams-mbp:Aut adam$ python main.py main.py -outfile thing
Usage:
main.py controller
main.py model
main.py form
main.py -h | --help
main.py --version
Options:
-h --help Show this screen.
--version Show version.
--outfile Output file.
adams-mbp:Aut adam$ python main.py main.py -outfile=thing
Naval Fate.
Usage:
main.py controller
main.py model
main.py form
main.py -h | --help
main.py --version
Options:
-h --help Show this screen.
--version Show version.
--outfile Output file.
adams-mbp:Aut adam$ python main.py main.py outfile=thing
Usage:
main.py controller
main.py model
main.py form
main.py -h | --help
main.py --version
Options:
-h --help Show this screen.
--version Show version.
--outfile Output file.
Seriously?
First of all, why are you calling your script twice?
python main.py main.py --outfile thing # Will not work
python main.py --outfile thing # This will be enough
Secondly, the usage section of docopt show you the different way to call your script.
Usage:
main.py controller
main.py model
main.py form
main.py -h | --help
main.py --version
main.py model work because it's described here. But --outfile appears nowhere in this Usage section so docopt consider it as a false input. And that's why the script always return the help.
If you want to use this option you have to describe it in "Usage".
You can do this like that :
Usage:
main.py controller
main.py model [--outfile]
The bracket tell that the option is not mandatory, use () for mandatory options.
Another point, even you first call show errors, options should not appear in the dictionnary, maybe you should leave a blank before in the documentation. Neither screen, or this. an so on...
Try something like that :
"""Main.py
Usage:
main.py controller [--outfile]
main.py model [--outfile]
main.py form [--outfile]
main.py (-h | --help)
main.py --version
Options:
-h, --help Show this screen.
--version Show version.
--outfile Output file.
"""
from docopt import docopt
if __name__ == '__main__':
arguments = docopt(__doc__, version='Main.py 1.0')
print(arguments)

docopt not working and proceeding

The following version 0.6.2 docopt string is not working although i dont find any error in it:
"""Usage:
somecommand.py [-n nos] [-u] [-c] [-s start]
Options:
-h show help
-u some reply
-n number to fetch
-c ask to do it
-s start from?
"""
on commandline:
somecommand.py -n 2 -s 5
Usage:
privateunreadlybrate.py [-n nos] [-u] [-c] [-s start]
the execution does not proceed and it keeps on showing usage for any command entered.
So where is the error?
The 'nos' value also has to be given in the 'options:' part, try this:
"""Usage:
somecommand.py [-n nos] [-u] [-c] [-s start]
Options:
-h show help
-u some reply
-n nos number to fetch
-c ask to do it
-s start start from?
"""

ipython not showing argparse help message

In my python script myscript.py I use argparse to pass command-line arguments. When I want to display the help information about the input arguments, I just do:
$ python myscript.py --help
If instead I want to use ipython to run my script, the help message won't be displayed. Ipython will display its own help information:
$ ipython -- myscript.py -h
=========
IPython
=========
Tools for Interactive Computing in Python
=========================================
A Python shell with automatic history (input and output), dynamic object
introspection, easier configuration, command completion, access to the
system shell and more. IPython can also be embedded in running programs.
Usage
ipython [subcommand] [options] [files]
It's not so annoying, but is there a way around it?
You need to run your .py script inside the ipython. Something like that:
%run script.py -h
This is an IPython bug, corrected in https://github.com/ipython/ipython/pull/2663.
My 0.13 has this error; it is corrected in 0.13.2. The fix is in IPthyon/config/application.py Application.parse_command_line. This function looks for help and version flags (-h,-V) in sys.argv before passing things on to parse_known_args (hence the custom help formatting). In the corrected release, it checks sys.argv only up to the first --. Before it looked in the whole array.
earlier:
A fix for earlier releases is to define an alternate help flag in the script:
simple.py script:
import argparse, sys
print(sys.argv)
p = argparse.ArgumentParser(add_help=False) # turn off the regular -h
p.add_argument('-t')
p.add_argument('-a','--ayuda',action=argparse._HelpAction,help='alternate help')
print(p.parse_args())
Invoke with:
$ ./ipython3 -- simple.py -a
['/home/paul/mypy/argdev/simple.py', '-a']
usage: simple.py [-t T] [-a]
optional arguments:
-t T
-a, --ayuda alternate help
$ ./ipython3 -- simple.py -t test
['/home/paul/mypy/argdev/simple.py', '-t', 'test']
Namespace(t='test')

Categories

Resources