当前位置: 首页 > 面试题库 >

单击命令行界面:如果未设置其他可选选项,则使选项为必需

司马腾
2023-03-14
问题内容

当使用Python
click库编写命令行界面(CLI)时,是否可以定义三个选项,其中仅当第一个(可选)选项未设置时才需要第二个和第三个选项?

我的用例是一个登录系统,该系统允许我通过authentication token(选项1)或通过username(选项2)和password(选项3)进行身份验证。

如果给出了令牌,则无需检查usernamepassword定义令牌或提示它们。否则,如果忽略了此令牌,然后usernamepassword成为必需的,必须给予。

可以使用回调以某种方式完成此操作吗?

我的入门代码当然不能反映预期的模式:

@click.command()
@click.option('--authentication-token', prompt=True, required=True)
@click.option('--username', prompt=True, required=True)
@click.option('--password', hide_input=True, prompt=True, required=True)
def login(authentication_token, username, password):
    print(authentication_token, username, password)

if __name__ == '__main__':
    login()

问题答案:

这可以通过构建从派生的自定义类来完成click.Option,并在该类中使用如下click.Option.handle_parse_result()方法:

自订类别:

import click

class NotRequiredIf(click.Option):
    def __init__(self, *args, **kwargs):
        self.not_required_if = kwargs.pop('not_required_if')
        assert self.not_required_if, "'not_required_if' parameter required"
        kwargs['help'] = (kwargs.get('help', '') +
            ' NOTE: This argument is mutually exclusive with %s' %
            self.not_required_if
        ).strip()
        super(NotRequiredIf, self).__init__(*args, **kwargs)

    def handle_parse_result(self, ctx, opts, args):
        we_are_present = self.name in opts
        other_present = self.not_required_if in opts

        if other_present:
            if we_are_present:
                raise click.UsageError(
                    "Illegal usage: `%s` is mutually exclusive with `%s`" % (
                        self.name, self.not_required_if))
            else:
                self.prompt = None

        return super(NotRequiredIf, self).handle_parse_result(
            ctx, opts, args)

使用自定义类:

要使用自定义类,请将cls参数传递给click.optiondecorator,如下所示:

@click.option('--username', prompt=True, cls=NotRequiredIf,
              not_required_if='authentication_token')

这是如何运作的?

之所以可行,是因为click是一个设计良好的OO框架。该@click.option()装饰通常实例化一个click.Option对象,但允许与被覆盖这种行为cls参数。因此,click.Option在我们自己的类中继承并超越所需的方法是相对容易的事情。

在这种情况下,我们在乘坐click.Option.handle_parse_result()和禁用需要user/password,如果authentication- token令牌存在,并且抱怨,如果两者user/passwordauthentication-token存在。

测试代码:

@click.command()
@click.option('--authentication-token')
@click.option('--username', prompt=True, cls=NotRequiredIf,
              not_required_if='authentication_token')
@click.option('--password', prompt=True, hide_input=True, cls=NotRequiredIf,
              not_required_if='authentication_token')
def login(authentication_token, username, password):
    click.echo('t:%s  u:%s  p:%s' % (
        authentication_token, username, password))

if __name__ == '__main__':
    login('--username name --password pword'.split())
    login('--help'.split())
    login(''.split())
    login('--username name'.split())
    login('--authentication-token token'.split())

结果:

来自login('--username name --password pword'.split())

t:None  u:name  p:pword

来自login('--help'.split())

Usage: test.py [OPTIONS]

Options:
  --authentication-token TEXT
  --username TEXT              NOTE: This argument is mutually exclusive with
                               authentication_token
  --password TEXT              NOTE: This argument is mutually exclusive with
                               authentication_token
  --help                       Show this message and exit.


 类似资料:
  • Node.js 自带了各种命令行选项。 这些选项开放了内置的调试、执行脚本的多种方式、以及其他有用的运行时选项。运行 man node 可在一个终端中查看操作手册。 概要 node [options] [v8 options] [script.js | -e "script" | -] [--] [arguments] node debug [script.js | -e "script" | <

  • Shebang 行 几乎每个 Perl 程序都如此开始: #!/usr/bin/perl 这是 UNIX 结构,它告诉 Shell 直接执行余下的输入程序文件。 你可以在此行添加 Perl 的任何命令行选项,它们将成为选项之后命令行的一部分。 如果你有一个程序包含: #!/usr/bin/perl -T 然后执行: perl -l program.pl -l 和 -T 两个选项都会使用,但

  • 进程优先权 当计划线程时使用的优先权。在有需要时可调整优先权到较高或较低。 文件位置 你可以为不同的文件类型改变文件夹。在默认情况下,大部分的文件设置在设置位置。然而, 一些文件是保存在 profiles目录和全部日志文件保存在 logs 目录。 文件关联(只限于完整版本) 文件关联是 Navicat 使用什么来打开 Navicat 已保存的文件。例如:.npt 文件(数据传输设置文件)将会使用数

  • 我希望,如果我选择“mammals”,动物选择选项只显示值为1的选项data-animal_class。 我知道如何获得哺乳动物值,但我不知道如何使用过滤器 这是我的代码:

  • Ruby 一般是从命令行运行,方式如下: 解释器可以通过下列选项被调用,来控制解释器的环境和行为。 选项 描述 -a 与 -n 或 -p 一起使用时,可以打开自动拆分模式(auto split mode)。请查看 -n 和 -p 选项。 -c 只检查语法,不执行程序。 -C dir 在执行前改变目录(等价于 -X)。 -d 启用调试模式(等价于 -debug)。 -F pat 指定 pat 作为默

  • Envoy由JSON配置文件以及一组命令行选项驱动。以下是Envoy支持的命令行选项。 -c \, --config-path \ (必选)指向v1或v2 JSON/YAML/proto3配置文件)的路径。若设置-v2-config-only选项,则将被解析为一个v2引导配置文件,如果是v1 JSON配置文件,则返回失败。对于v2配置文件,有效的扩展名是.json,.yaml,.pb和.pb_te