繁体   English   中英

docopt解析不返回预期的字典

[英]docopt parsing doesn't return the expected dictionary

我想做同样的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”),只会出现错误信息!

前两个实际工作,这里是现场演示:

wplan - 进步

wplan - 强迫

最后需要修改以匹配使用模式,例如:

wplan --verbosity 3


阅读你的代码,我认为这将避免使用pseudo_docopt函数,允许使用真正的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 ,所以仅使用except Exception将无法正常工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM