It's the first time I use docopt and I'm struggling with the args parsing for a small command line program I'm trying to realize.
'''Usage:
ovh_mails.py list [--ugly]
ovh_mails.py add (<address> [--pswd=<password>][--description=<description>] | --file <filename>)
ovh_mails.py remove (<address> | --file <filename>)
ovh_mails.py (-h | --help)
Arguments:
<password> Password to access the mailbox (if not provided it's random generated)
<filename> Name of the files to process. Check README to see how to format it
Options:
-h, --help Show this help message
-u, --ugly Print without nice tables
-p, --pswd=<password> Set the password to the one provided
Commands:
list list all the email addresses currently configured
add add one or more (configured in <filename>) email addresses
remove remove one ore more (configured in <filename>) email addresses'''
The parsing of the arguments I have at the moment is:
if __name__ == '__main__':
args = docopt(__doc__)
#Validate args ---- TODO
# 'List' command parsing
if args['list']:
if args['--ugly']:
eman = EmailManager(niceoutput=False)
else:
eman = EmailManager()
eman.list_emails()
# 'Add' command parsing
elif args['add']:
if args['<address>']:
eman = EmailManager()
emails = (
{
'address': args['<address>'],
'password': None,
'description': None,
},
)
if args['--description']:
emails[0]['description'] = args['<description>']
if args['--pswd']:
emails[0]['password'] = args['<password>']
if args['--file']:
raise NotImplemented
eman.add_emails(emails)
# 'remove' command parsing
elif args['remove']:
if args['<address>']:
eman = EmailManager()
emails = (
{
'address': args['<address>'],
},
)
eman.remove_emails(emails)
if args['--file']:
raise NotImplemented
Is there a better, more pythonic ore more elegant way, to do this?
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 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'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)
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 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)
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)
can anyone show me how can I test a cli app written in Docopt (Python)? Someone on GitHub posted this,
import unittest
from docopt import docopt
import your.entry.point.of.sum as sum
# you can import the doc string from the sum module
doc = sum.__doc__
# suppose now the doc is:
# Sum two numbers.
# Usage: summation.py <x> <y>
# then write your test cases
class TestCLIParser(unittest.TestCase):
def test_sum(self):
args = docopt(doc, ["1", "3"])
self.assertEqual(args["<x>"], "1")
self.assertEqual(args["<y>"], "3")
def and_so_on(self):
...
I have got this but can someone show me how can I test the output of the program? This example only tests the arguments
Source: (StackOverflow)
According to PEP 257 the docstring of command line script should be its usage message:
The docstring of a script (a stand-alone program) should be usable as its "usage" message, printed when the script is invoked with incorrect or missing arguments (or perhaps with a "-h" option, for "help"). Such a docstring should document the script's function and command line syntax, environment variables, and files. Usage messages can be fairly elaborate (several screens full) and should be sufficient for a new user to use the command properly, as well as a complete quick reference to all options and arguments for the sophisticated user.
And the the docstring shall be the first string as module level, before anything else, to be available as __doc__
.
Now, I'm also using docopt
as a usage message parser, so I just have to write the doc string, and it's building the command line parser on its own, and that's great.
_("""...""")
What's not that great, is that I can't find a way to mark the docstring as i18nable for gettext, so I can convert it to other languages when given to docopt
. At the time being the only solution I got is to make the usage and help messages stay in english, when all the application's other strings are translated!
As the PEP 20 states:
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
What would be the best way to get around the limitation of not being able to mark the docstring as translatable elegantly?
N.B.: here we consider that I'm doing the gettext.install()
in the __init__.py
module so that _()
is present in the builtins before even __doc__
is being parsed.
Source: (StackOverflow)