docopt解析未返回预期的字典

时间:2019-06-24 20:59:29

标签: python docopt

我想使用相同的cli工具并尝试docopt,但我挣扎了很多次:

这是我的文档字符串:

"""
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
""" 

但是以下cli字符串中没有一个产生docopt字典:

  • “ wplan --progress”->没有字典->使用情况屏幕
  • “ wplan --forced”->没有字典->使用情况屏幕
  • “ wplan --verbose”->没有字典->使用情况屏幕

好-我用该文件测试docopt内容:

#!/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()

因此,如果我运行此docoptest.py文件(“ python3.7 docopttest.py”),则仅显示错误信息!

1 个答案:

答案 0 :(得分:0)

前两个实际可行,这是现场演示:

wplan --progress

wplan --forced

最后一个需要修改以匹配使用模式,例如像这样:

wplan --verbosity 3


阅读您的代码,我认为这将避免使用该4 |> f1 (1,2) |> f2 函数,从而允许使用真正的docopt:

pseudo_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)) 继承自DocoptExit,后者继承了SystemExit的形式,因此仅使用BaseException无效。