python - 我可以使用上下文值作为 click.option() 默认值吗?

标签 python command-line-interface python-click

我想在我的配置(我加载到我的上下文中)中使用一个值作为单击命令选项的默认值。我读过 this section的文档,我不认为我理解我需要做什么。

这是我的示例脚本:

import sys
import click

@click.group()
@click.pass_context
def cli(ctx):
    """
    CLI
    """
    ctx.ensure_object(dict)
    ctx.obj['DEFAULT_ENVIRONMENT'] = "dev"


@cli.command()
@click.option('-e', '--environment', required=True, default=click.get_current_context().obj['DEFAULT_ENVIRONMENT'])
def show_env(environment):
    click.echo(environment)


if __name__ == '__main__':
    cli()

如果我运行 python cli.py show-env,目标是让它输出 dev(因为我没有在加载时传递参数从上下文)。

这失败了

Traceback (most recent call last):
  File "testcli.py", line 15, in <module>
    @click.option('-e', '--environment', required=True, default=click.get_current_context().obj['DEFAULT_ENVIRONMENT'])
  File "/home/devuser/.virtualenvs/cli/lib/python3.6/site-packages/click/globals.py", line 26, in get_current_context
    raise RuntimeError('There is no active click context.')
RuntimeError: There is no active click context.

我也尝试过在我的 show_env 命令上使用 @pass_context,如下所示:

@cli.command()
@click.option('-e', '--environment', required=True, default=ctx.obj['DEFAULT_ENVIRONMENT'])
@click.pass_context
def show_env(ctx, environment):
    click.echo(environment)

失败是因为 ctx 在那个时候没有定义。

Traceback (most recent call last):
  File "testcli.py", line 15, in <module>
    @click.option('-e', '--environment', required=True, default=ctx.obj['DEFAULT_ENVIRONMENT'])
NameError: name 'ctx' is not defined

我可以使用我的上下文来设置命令选项默认值吗?

最佳答案

正如您所指出的,在您尝试检查上下文时上下文尚不存在。您可以延迟从上下文中进行默认查找,直到上下文确实存在,方法是使用自定义类,例如:

自定义类

def default_from_context(default_name):

    class OptionDefaultFromContext(click.Option):

        def get_default(self, ctx):
            self.default = ctx.obj[default_name]
            return super(OptionDefaultFromContext, self).get_default(ctx)

    return OptionDefaultFromContext

使用自定义类

要使用自定义类,请通过 cls 参数将其传递给 click.option,例如:

@click.option('-e', '--environment', required=True,
              cls=default_from_context('DEFAULT_ENVIRONMENT'))

这是如何运作的?

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

在这种情况下,我们覆盖 click.Option.get_default()。在我们的 get_default() 中,我们检查上下文并设置默认值。然后我们调用父级 get_default() 继续进一步处理。

测试代码:

import click

@click.group()
@click.pass_context
def cli(ctx):
    """
    CLI
    """
    ctx.ensure_object(dict)
    ctx.obj['DEFAULT_ENVIRONMENT'] = "dev"


@cli.command()
@click.option('-e', '--environment', required=True,
              cls=default_from_context('DEFAULT_ENVIRONMENT'))
def show_env(environment):
    click.echo(environment)


if __name__ == "__main__":
    commands = (
        'show_env',
        '--help',
    )

    import sys, time
    time.sleep(1)
    print('Click Version: {}'.format(click.__version__))
    print('Python Version: {}'.format(sys.version))
    for cmd in commands:
        try:
            time.sleep(0.1)
            print('-----------')
            print('> ' + cmd)
            time.sleep(0.1)
            cli(cmd.split())

        except BaseException as exc:
            if str(exc) != '0' and \
                    not isinstance(exc, (click.ClickException, SystemExit)):
                raise

结果:

Click Version: 6.7
Python Version: 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 05:52:31) 
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.57)]
-----------
> show_env
dev
-----------
> --help
Usage: click_prog.py [OPTIONS] COMMAND [ARGS]...

  CLI

Options:
  --help  Show this message and exit.

Commands:
  show_env

关于python - 我可以使用上下文值作为 click.option() 默认值吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56042757/

相关文章:

python - 为什么 (0>1 + 0>9) 返回 False,而 ((0>1) + (0>9)) 返回 0?

python - 将 OneClassSVM 与 cross_val_score 结合使用

google-cloud-platform - 如何使用 CLI 命令更改 GCP 中的项目

python - 如何在 Click 链接组中对命令列表显示进行分类?

python - python-click MultiCommand 的全局选项

python - 谷歌应用服务器 "unable to add testProject to attribute application"正则表达式问题中的 yaml 异常?

python - 从 Python 字符串中去除标点符号

ubuntu - 为什么 GIMP 脚本在 CLI 模式下不起作用?

python - 如何向子命令添加通用选项,这些选项可以在子命令的名称 * 之后 *

python - 如何存储单击命令行参数/选项以供引用?