docopt
Pythonic command line arguments parser, that will make you smile
docopt—language for description of command-line interfaces
I am having issues getting docopt to parse arguments that contain spaces into a proper dictionary object for use with my unit tests.
Here is the code I'm currently using to construct the argument list for docopt to parse:
testargs = []
def clear_args():
testargs[:] = []
return
def add_testfiles(file1='defaultfile1.txt', file2='defaultfile2.txt'):
clear_args()
testargs.append('--debug')
testargs.append(file1)
testargs.append(file2)
return
def parse_args(optlist):
argstr = ' '.join(optlist)
return docopt(downpost.__doc__, argv=argstr)
The code I am writing unit tests for has 2 tests that are separately given the following arguments:
-t <title> # <title> can be any string (with spaces) inside quotation marks
"A Filename with Spaces.txt" # any filename as long as it's in quotation marks
To add, for example, the -t argument, I would do:
def test_exampleunittest(self):
add_testfiles()
testargs.append('-t "This is the title I want"')
self.args = parse_args(testargs)
self.post = myPythonScript.process(self.args)
self.assertEqual(self.post['Subject'], 'This is the title I want')
If I run the script I'm testing by itself with the said arguments, they are accepted without any problems and the output is as expected.
However, if I run the unit tests which use arguments containing spaces, I get the following:
DocoptExit: Usage: myPythonScript [options] <file_1> <file_2>
Other unit tests that require the same dict object (containing the same arguments) work fine.
What should I change in my code to make docopt parse the arguments as it normally does?
Source: (StackOverflow)
When followint the docopt README, I would expect the following file to produce some valid output:
#!/usr/bin/env python
"""Example file.
Usage:
test_docopt.py test
test_docopt.py (-h | --help)
test_docopt.py --version
Options:
-h --help Show this screen
--version Show version.
"""
import pkg_resources
pkg_resources.require("docopt==0.6.1")
from docopt import docopt
if __name__ == '__main__':
args = docopt(__doc__, version="Extend limb profiles 0.1")
print(args)
However, when I call test_docopt.py
, I only get a meaningless/empty Usage statement:
$ python test_docopt.py test
Usage:
My two questions are:
- Why is docopt apparently failing to recognize the test command?
- Why isn't the Usage pattern filled with the actual usage pattern?
Source: (StackOverflow)
I have a few detailed option specifications in the docstring used for configuration of Docopt. Some of the items are quite lengthy. Is there a way of wrapping the text to make it more legible or to make it fit to a line width more easily?
Let's say the relevant bit of text in the docstring is the following:
Usage:
program [options]
Options:
-h, --help Show this help message.
-c, --configuration=CONF Configuration (file) [default: None]
-f, --files=FILESLIST Comma-delimited list of input data files [default: 169888_ttH_el.root]
-v, --variables=VARIABLESLIST Comma-delimited list of variables to plot [default: trk_pt]
-t, --tree=TREE Tree in input data files [default: mini]
-u, --username=USERNAME Username
-t, --topanalysis=DIRECTORY Directory of TopRootCore or TopAnalysis [default: /home/user/Dropbox/TopAnalysis]
-s, --superlongoption=TEST This is a very long option that requires a bit of text to explain it. [default: 101001011011101010010100110101010]
--version Show the version and exit.
Would it be possible wrap the text in a style something like the following?
Usage:
program [options]
Options:
-h, --help Show this help message.
-c, --configuration=CONF Configuration (file) [default: None]
-f, --files=FILESLIST Comma-delimited list of input data files
[default: 169888_ttH_el.root]
-v, --variables=VARIABLESLIST Comma-delimited list of variables to plot
[default: trk_pt]
-t, --tree=TREE Tree in input data files [default: mini]
-u, --username=USERNAME Username
-t, --topanalysis=DIRECTORY Directory of TopRootCore or TopAnalysis
[default: /home/user/Dropbox/TopAnalysis]
-s, --superlongoption=TEST This is a very long option that requires a
bit of text to explain it.
[default: 101001011011101010010100110101010]
--version Show the version and exit.
Source: (StackOverflow)
I have a bash script that uses docopts. It works beautifully on my Debian machine, but fails to set defaults on my Ubuntu laptop. Here's the docopts code:
eval "$(docopts -A args -V - -h - : "$@" <<EOF
Usage: cmus_select.sh [--list <tag>] [--random] [--structure=</alt/dir/structure>] [--dir=/path/to/music]
-h --help Show help
-r --random Randomize selection instead of using a dmenu
-l --list TAG List music by tag. Unless you use -s, genre, artist, album, and song are expected. [default: song]
-s --structure STRUCT Directory structure for your music. [default: genre/artist/album/song]
-d --dir DIR Location of music [default: $HOME/Music/]
----
cmus_select.sh 0.0.1
EOF
)"
- I found the two spaces requirement and already checked that (not sure if stackoverflow formatting will eat the spaces.)
- Both machines use docopts 0.6.1+fix. The debian machine uses bash 4.2.37 and python 2.7.3. The ubuntu machine is on 4.2.45 and 2.7.5+.
- I tried a variety of ways to describe the options. Different order of -l/--list. = sign between the option and its variable. Var name in angle brackets. Etc. It reliably works in debian and not in Ubuntu.
-- followup--
I encountered the same problem on a debian testing machine. Docopts is looking for a new maintainer so I gave up. As an alternative I wrote https://raw.github.com/sagotsky/.dotfiles/612fe9e5c4aa7e1fae268810b24f8f80960a6d66/scripts/argh.sh which is smaller than docopts but does what I need.
Source: (StackOverflow)
I have a really simple code with docopt which creates a directory. The program works perfectly like this:
dbb create_dir
I need to run this using crontab in ubuntu 12.04. I used crontab -e
and added this line:
0 14 * * * dbb create_dir
which should run the code on 2pm every day. My problem is this doesn't work. I checked
0 14 * * * mkdir test_dir
and it worked. So I thought the problem is not with the cron and as I could run the code without cron, I guess the main problem is the combiniation of these two. Is there any way to fix this? Thanx
Source: (StackOverflow)
Using docopt, is there a way to make a double-dashed parameter that works with and without an equals sign?
I want both of the following commands to make --tls be true:
cmd --tls
cmd --tls=true
I seem to only be able to get one or the other to work by using
Options:
--tls
or
Options:
--tls=false
Separating them by a comma does not seem to work
Options:
--tls, --tls=false
Source: (StackOverflow)
I have a command which I use in docopt which looks like this:
cli.py argument_test (--required_id=<required_id> | --required_name=<required_name>) (--required=<required>) (--repeat=<repeat>)... (--required_named=<required_named> | <required_named>) (--thisflag | --thatflag) [--optionalflag] [--optional_named=<optional_named>]
I need some way of parsing this into a structure which could present the information like this (on a web page for example)
RequiredArguments: required_id or requiredname, required, repeat(list), required_named, thisflag(bool) or thatflag(bool)
OptionalArguments: optionalflag(bool), optionalnamed
Docopt parses the pattern into an object with children which looks like the following:
Required(Command('argument_test', False), Required(Either(Option(None, '--required_id', 1, None), Option(None, '--required_name', 1, None))), Required(Option(None, '--required', 1, None)), OneOrMore(Required(Option(None, '--repeat', 1, []))), Required(Either(Option(None, '--required_named', 1, None), Argument('<required_named>', None))), Required(Either(Option(None, '--thisflag', 0, False), Option(None, '--thatflag', 0, False))), Optional(Option(None, '--optionalflag', 0, False)), Optional(Option(None, '--optional_named', 1, None)))))
I'm pretty stumped where to go from here in how I should go about parsing these. Any advice is appreciated!
Source: (StackOverflow)
I'm trying to understand how to access multiple input arguments from docopt.Parse() output.
Example:
package main
import (
"fmt"
"github.com/docopt/docopt-go"
)
func main() {
usage := `blah.go
Usage:
blah.go read <file> ...
blah.go -h | --help | --version`
arguments, _ := docopt.Parse(usage, nil, true, "blah 1.0", false)
x := arguments["<file>"]
fmt.Println(x)
fmt.Println(x)
}
Command Line:
$ go run blah.go read file1 file2
[file1 file2]
[file1 file2]
I'd like to print out only file1 or file2.
When I try adding:
fmt.Println(x[0])
I get the following error:
$ go run blah.go read file1 file2
# command-line-arguments
./blah.go:19: invalid operation: x[0] (index of type interface {})
https://github.com/docopt/docopt.go
Source: (StackOverflow)
I'm trying to use docopt.
i want to call my program like this:
python3 my_script -p argum1 -d argum2 -u faculm
The -u is not mandatory, but "-p" and "-d" are mandatory.
i have allready made this:
"""
Usage:
passwdcrack.py -p=<password>,
passwdcrack.py -d=<dicionario>
passwdcrack.py [-u=<user>]
Options:
-h --help mostra este ecrã
--version Mostra a versão
-p=<password> indicar o caminho para o ficheiro tipo */etc/shadow
-d=<dicionario> indicar o caminho para o ficheiro com lista de Passw
-u=<user> indica o utilizador para ser analisado
"""
import docopt
if __name__ == '__main__':
arguments = docopt.docopt(__doc__, version='0.0001')
print (arguments)
but when i call it it gives me this:
$ python3 passwdcrack.py -d papa -d pfpf -u madona Traceback (most
recent call last): File "passwdcrack.py", line 17, in
arguments = docopt.docopt(doc, version='0.0001') AttributeError: 'module' object has no attribute 'docopt'
Can some one help me?
thanks
Source: (StackOverflow)
If I have a command-line program written in Python (specifically using docopt which uses argparse I think), and I want to run it as my-program command1 args
instead of python my-program.py command1 args
, what do I have to do? For now, this is for Debian-based OS (e.g Ubuntu).
I normally make my module a package so I already have setup.py
but that doesn't grant me a free command.
Thanks!
EDIT
@pyrospade gave a very good link below. I am going to share my result.
Suppose we have
top-level-directory
setup.py
package/
__init__.py
cli.py
You can use scripts=['package/cli.py']
if you want to access cli.py
in the shell.
If you want to run as my-cli
, you can use
entry_points={
'console_scripts':
['my-cli=package.cli:main']
}
Since I use docopt
, I have this
def dispatcher(...)
def fun1(....)
def main():
arguments = docopt(COMMAND, version="xxxx")
dispatcher(arguments)
if __name__ == '__main__':
main()
You can even put it under __init__.py
by saying ['my-cli=package:main']
but again, you need a function called main()
. But you can name it whatever you want. Just saying.
Source: (StackOverflow)
I'm trying to create a command-line interface using docopt. Here is a simplified version of my file:
#!/usr/bin/env python
"""
Test program.
Usage:
test.py [options]
Options:
-a <input>
-b
-c
-d
"""
import docopt
print docopt.docopt(__doc__)
I essentially want to be able to specify any of the options, in any order. However, if I forget to specify the argument for the -a
flag, then I get an output like this:
$ python test.py -a -b -c
{"-a": "-b",
"-b": False,
"-c": True,
"-d": False}
Docopt is treating the -b
flag as the argument for the -a
flag, instead of rejecting the input as invalid. Is there some easy way to detect this, or make docopt refuse to accept this sort of malformed input?
Source: (StackOverflow)
I want to pass two mandatory argument, one optional argument to my program using docopt. The code I am using is:
"""Setup
Usage: myprog.py server_name config [--help] [options]
Arguments:
SERVER_NAME Server Name (a1, a2)
CONFIG Config file with full path
Options:
-h --help
-r --start Start the server if yes [default: 'no']
"""
from docopt import docopt
class ServerSetup(object):
def __init__(self, server_name, config_file, start_server):
self.server = server_name
self.config = config_file
self.start_server = start_server
def print_msg(self):
print self.server
print self.config
print self.start_server
if __name__ == '__main__':
args = docopt(__doc__)
setup = ServerSetup(server_name=args['SERVER_NAME']),
config=args['CONFIG']
start_rig=args['-r'])
setup.print_msg()
$python myprog.py a1 /abc/file1.txt
When I run above program using above command, I get error message displaying usage that I've written. What is going wrong here, how can I use more than one 'Arguments'?
Source: (StackOverflow)
I'm working on a large project with multiple authors, so I'm trying to avoid making too many changes. I have one script which uses docopt to pass options, and sets some of them to default values.
I loaded a class from that script by importing it as a module, but when I called a method, it failed because it expected a default option to be set by docopt, of which there are many. Is there a way to pull in the default options from docopt?
Source: (StackOverflow)
I want my script accepts command line args like "cp" command does:
'''
Usage:
cp.py <source>... <directory>
cp.py -t <directory> <source>...
cp.py -s <source>... -t <directory>
'''
Those command line
$ python cp.py src/path/1 src/path/2 target/path
$ python cp.py -t target/path src/path/1 src/path/2
$ python cp.py -s src/path/1 src/path/2 -t target/path
will get the same result:
{'<source>':['src/path/1', 'src/path/2'],'<directory>': 'target/path'}
Thx very much. And sorry for my English:)
Source: (StackOverflow)
I am adding validation using schema for CLI that uses docopt, but I cannot seem to get optional to work. I want to validate that:
- the input file exists
- valid options are used
- if the PATH is added that the directory exists.
Here is app so far
"""DVget
Usage:
DVget [-s] FILE [PATH]
Process a file, return data based on selection
and write results to PATH/output-file
Arguments:
FILE specify input file
PATH specify output directory (default: ./)
Options:
-s returns sections
-p returns name-sets
-m returns modules
"""
import os
from docopt import docopt
from schema import Schema, And, Use, Optional, SchemaError
# START OF SCRIPT
if __name__ == "__main__":
arguments = docopt(__doc__, version="0.1")
#print(arguments)
schema = Schema({
'FILE': [Use(open, error='FILE should be readable')],
Optional('PATH'): And(os.path.exists, error='PATH should exist'),
'-': And(str, lambda s: s in ('s', 'p', 'm'))})
try:
arguments = schema.validate(arguments)
# process(arguments)
except SchemaError as e:
exit(e)
running DVget -s "c:\test.txt" gives me the error message 'PATH should exist' even when using Optional in schema and docopt. Any suggestions?
Source: (StackOverflow)