I wanna do same cli tools and tried docopt but i struggled many times:
here's my docstring:
"""
usage:
wplan [--progress] [--forced] [--path DIR]
[--verbosity VMODE]
wplan -h
options:
--progress show progress bar
--forced force overwrite
--path DIR ddsfwefafef [default: /path/to/file]
--verbosity VMODE asdfasdf [default: 1]
-h some help
"""
But no one of the following cli strings results in a docopt dictionary:
Ok - i testet the docopt stuff with that file:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import sys
import os
# to run docopt.docopt in a test: replace DocoptExit in docopt
# func
from docopt import \
DocoptExit, printable_usage, parse_defaults, parse_pattern, \
formal_usage, TokenStream, parse_argv, Option, Dict, \
AnyOptions, extras
def pseudo_docopt(doc, argv=None, help=True, version=None,
options_first=False):
"""Thats a copy of docopt.docopt function. Only the last line
the "DocoptExit()" statement ist replaced by "raise RuntimeError".
"""
if argv is None:
argv = sys.argv[1:]
DocoptExit.usage = printable_usage(doc)
options = parse_defaults(doc)
pattern = parse_pattern(formal_usage(DocoptExit.usage), options)
argv = parse_argv(TokenStream(argv, DocoptExit), list(options),
options_first)
pattern_options = set(pattern.flat(Option))
for ao in pattern.flat(AnyOptions):
doc_options = parse_defaults(doc)
ao.children = list(set(doc_options) - pattern_options)
extras(help, version, argv, doc)
matched, left, collected = pattern.fix().match(argv)
if matched and left == []: # better error message if left?
return Dict((a.name, a.value)
for a in (pattern.flat() + collected))
# if code goes here no dict is sent
raise RuntimeError()
# some command line tests
cltests = [
[],
# 1 arg
["--progress"],
["--forced"],
# 2 args
["--progress", "--forced"],
["--forced", "--progress"],
["--path /path/to/file"],
["--verbosity", "2"],
# 3 args
["--progress", "--path", "/path/to/file"],
["--forced", "--path", "/path/to/file"],
["--progress", "--verbosity", "2"],
["--forced", "--verbosity", "2"],
# 4 args
["--forced", "--progress", "--path", "/path/to/file"],
["--progress", "--forced", "--path", "/path/to/file"],
["--forced", "--progress", "--verbosity", "2"],
["--progress", "--forced", "--verbosity", "2"],
]
# the __doc__ fake
doc = """
usage:
wplan [--progress] [--forced] [--path DIR]
[--verbosity VMODE]
wplan -h
options:
--progress show progress bar
--forced force overwrite
--path DIR ddsfwefafef [default: /path/to/file]
--verbosity VMODE asdfasdf [default: 1]
-h some help
"""
for args in cltests:
cmd = ["wplan", ] + args
info = "run {}".format(cmd)
print(info + os.linesep + "-" * len(info))
try:
data = pseudo_docopt(doc=doc, argv=cmd)
assert isinstance(data, dict)
assert "--progress" in data
assert "--progress" in data
assert "--forced" in data
assert "--path" in data
assert "--verbosity" in data
print("... OK there is a docopt dict")
except RuntimeError:
print("... ERROR: no docopt dict for: {}".format(cmd))
print()
So if i run this docoptest.py file ("python3.7 docopttest.py") only the ERROR info appears!
First two actually work, here are the live demos:
The last needs to be modified to match the usage pattern, eg like this:
Reading your code, I think this will avoid the need for that pseudo_docopt
function, allowing use of the real docopt:
for args in cltests:
... # same
try:
data = docopt.docopt(doc=doc, argv=cmd)
... # assert, print... same
except DocoptExit:
print("... ERROR: no docopt dict for: {}".format(cmd))
Note that DocoptExit
inherits from SystemExit
which inherits form BaseException
, so using just except Exception
won't work.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.