跳转到主要内容

对argparse的改进:额外操作,子解析器别名,智能格式化,基于装饰器的包装器

项目描述

此软件包在两个级别上对argparse进行了扩展

  • 基本argparse扩展:默认子解析器,2.X中的子解析器别名

  • 可以为add_argument指定的附加操作

  • 智能格式化器,允许组合默认帮助格式化和原始描述

  • 使用装饰器的argparse包装器

基本argparse的扩展

将以下内容插入以在2.6和2.7的子解析器定义中指定 别名

from __future__ import print_function

import sys
from ruamel.std.argparse import ArgumentParser, SubParsersAction

parser = ArgumentParser()
if sys.version_info < (3,):  # add aliases support
    parser.register('action', 'parsers', SubParsersAction)
subparsers = parser.add_subparsers()
checkout = subparsers.add_parser('checkout', aliases=['co'])
checkout.add_argument('foo')
args = parser.parse_args(['co', 'bar'])
print(args)

结果如下

Namespace(foo='bar')

附加操作

CountAction

上下计数

from __future__ import print_function

from ruamel.std.argparse import CountAction
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action=CountAction, const=1, nargs=0)
parser.add_argument('--quiet', '-q', action=CountAction, dest='verbose',
                    const=-1, nargs=0)

print(parser.parse_args("--verbose -v -q".split()))

结果如下

Namespace(verbose=1)

SplitAppend

在“,”之后追加。运行

from __future__ import print_function

from ruamel.std.argparse import SplitAppendAction
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('-d', action=SplitAppendAction)

print(parser.parse_args("-d ab -d cd -d kl -d mn".split()))
print(parser.parse_args("-d ab,cd,kl,mn".split()))
print(parser.parse_args("-d ab,cd -d kl,mn".split()))

结果如下

Namespace(d=['ab', 'cd', 'kl', 'mn'])
Namespace(d=['ab', 'cd', 'kl', 'mn'])
Namespace(d=['ab', 'cd', 'kl', 'mn'])

CheckSingleStoreAction

如果同一个选项被多次调用,则发出警告

from __future__ import print_function

from ruamel.std.argparse import CheckSingleStoreAction
import argparse

parser = argparse.ArgumentParser()
parser.add_argument('--check', '-c', action=CheckSingleStoreAction, const=1,
                    nargs=0)

print(parser.parse_args("--check -c".split()))

结果如下

WARNING: previous optional argument "-c []" overwritten by "-c []"
Namespace(check=[])

智能格式化

您只能指定一个格式化器在标准的argparse中,因此您不能同时具有预格式化的描述和默认参数。使用RawDescriptionHelpFormatter以及ArgumentDefaultsHelpFormatter。

SmartFormatterargparse.HelpFormatter 的子类,并且默认情况下有正常的格式化器。帮助文本可以在开头标记以进行格式化变化

  • "R|.." 格式原始,即不要包装和填充,观察换行

  • "*|.." 格式密码帮助,永远不回显密码默认值

  • "D|.." 将默认值添加到 所有 条目中(这就是为什么 *| 很重要的原因)

版本字符串使用_split_lines格式化,并保留版本字符串中的任何换行符。

from __future__ import print_function

from ruamel.std.argparse import SmartFormatter
import argparse


def exit(self, *args, **kw):
    pass

argparse.ArgumentParser.exit = exit

# the 'D|....' in the second pass triggers generating defaults for all entries,
# while being smart about which one already have a %(default)s

for index, log_s in enumerate(['log to file', 'D|log to file']):
    parser = argparse.ArgumentParser(formatter_class=SmartFormatter)

    parser.add_argument('--log', default='abc.log', help=log_s)
    parser.add_argument('--username',
                        help='username to login with (default: %(default)s)')
    parser.add_argument('--password', help='*|password to use for login')
    parser.add_argument('--recursive', '-r', action='store_true',
                        help="R|recurse into subdirectories \nto find files")
    parser.set_defaults(username='anthon', password="test123")

    if index > 0:
        print('--------------------------------------\n')
    parser.parse_args(["--help"])

结果如下

usage: smartformatter.py [-h] [--log LOG] [--username USERNAME]
                         [--password PASSWORD] [--recursive]

optional arguments:
  -h, --help           show this help message and exit
  --log LOG            log to file
  --username USERNAME  username to login with (default: anthon)
  --password PASSWORD  password to use for login
  --recursive, -r      recurse into subdirectories
                       to find files
--------------------------------------

usage: smartformatter.py [-h] [--log LOG] [--username USERNAME]
                         [--password PASSWORD] [--recursive]

optional arguments:
  -h, --help           show this help message and exit
  --log LOG            log to file (default: abc.log)
  --username USERNAME  username to login with (default: anthon)
  --password PASSWORD  password to use for login (default: *******)
  --recursive, -r      recurse into subdirectories
                       to find files (default: False)

包装argparse

当使用argparse与子解析器结合时,每个子解析器都有自己的功能(使用.set_defaults(func=function)可以调用,存在大量重复代码。

ProgramBase类提供了另一种解决方案,该类应该被继承,并且可以应用于该子类方法的sub_parseroptionversion装饰器。

一个典型的用法是

from __future__ import print_function

import sys
import os

from ruamel.std.argparse import ProgramBase, option, sub_parser, version, \
    SmartFormatter


class TestCmd(ProgramBase):
    def __init__(self):
        super(TestCmd, self).__init__(
            formatter_class=SmartFormatter
        )

    # you can put these on __init__, but subclassing TestCmd
    # will cause that to break
    @option('--quiet', '-q', help='suppress verbosity', action='store_true',
            global_option=True)
    @version('version: 1.2.3')
    def _pb_init(self):
        # special name for which attribs are included in help
        pass

    def run(self):
        if self._args.func:
            return self._args.func()

    def parse_args(self, *args):
        self._parse_args(*args)

    @sub_parser(help='specific help for readit')
    @option('--name', default='abc')
    def readit(self):
        print('calling readit')

    @sub_parser('writeit', help='help for writeit')
    @option('--target')
    def other_name(self):
        print('calling writeit')


n = TestCmd()
n.parse_args(['--help'])
n.run()

和输出

usage: testcmd.py [-h] [--quiet] [--version] {readit,writeit} ...

positional arguments:
  {readit,writeit}
    readit          specific help for readit
    writeit         help for writeit

optional arguments:
  -h, --help        show this help message and exit
  --quiet, -q       suppress verbosity
  --version         show program's version number and exit

默认情况下,方法名称是子解析器的名称。这可以通过向sub_parser提供非关键字参数来覆盖。关键字参数传递给add_parser方法。

option函数相当于add_argument。如果option被放在一个不是子解析器的函数上,那么这样的选项将是一个全局选项。这些选项在调用脚本时必须在任何子解析器参数之前指定。通常使用global_option=True关键字参数指定这样的选项是非常方便的。这确保了选项被添加到所有子解析器中。这使得您可以调用prog --quiet writeitprog writeit --quiet)。您可以将这些选项分配给__init__,但是当继承TestCmd时,这可能会导致问题。因此,如果可能发生继承,最好将它们放在特殊处理的方法_pb_init上。

在扫描子解析器时,应注意访问TestCmd上的所有属性。特别是任何属性方法都将被访问并执行其代码。

默认命令

如果您希望特定的子解析器作为默认解析器调用,您可以使用

self._parse_args(default_sub_parser='show')

使以下在名为pass的程序命令行上的调用相同

pass
pass show

所有子命令的帮助信息

如果您向self._parse_args()的可选帮助所有参数提供了True值

self._parse_args(help_all=True)

则命令行将检查--help-all选项,并打印全局帮助信息,随后是每个子解析器的帮助信息,用虚线分隔。

测试

使用tox进行测试,它使用virtualenvpytest

项目详情


下载文件

下载适用于您的平台的文件。如果您不确定要选择哪一个,请了解更多关于安装包的信息。

源代码分发

ruamel.std.argparse-0.8.3.tar.gz (25.0 kB 查看哈希值)

上传 源代码

构建分发

ruamel.std.argparse-0.8.3-py2.py3-none-any.whl (14.6 kB 查看哈希值)

上传于 Python 2 Python 3

由以下支持