如果调用特定的子命令,执行不同的父命令操作?
Perform different parent command actions if specific subcommand is called?
在正常情况下,我的应用程序会将一组配置值加载到上下文中,这些值将通过 pass_context
传递给子命令。只有一种情况下这不起作用 - 第一次应用程序是 运行 并且尚未设置配置。
我的目标是允许用户 运行 一个子命令并生成适当的配置,以便 CLI 在其余时间正常工作。
我的cli.py
代码:
import sys
import click
from ruamel.yaml import YAML
from pathlib import Path
from commands.config_cmds import configcmd
MYAPP = "AwesomeCLI"
@click.group()
@click.version_option()
@click.pass_context
def cli(ctx):
"""command line application"""
ctx.ensure_object(dict)
ctx.obj['APPLICATION_NAME'] = MYAPP
config_file = Path(click.get_app_dir(ctx.obj[MYAPP])) / "config.yml"
yaml = YAML(typ="safe")
try:
config_yml = yaml.load(config_file)
except FileNotFoundError:
click.secho("Run command: awesome-cli configcmd first-run", fg='red')
raise click.FileError(config_file.name, "Missing configuration file.")
ctx.obj['CONFIG'] = yaml.dump(config_yml)
cli.add_command(configcmd)
我的configcmd
代码:
@click.group()
def configcmd():
"""Manage configuration of this tool
\f
The configuration file is saved in $HOME/.config/awesome-cli
"""
@config.command()
@click.pass_context
def first_run(ctx):
"""
Set up CLI configuration.
"""
api_key = click.prompt("Your API Key")
# More stuff here about saving this file...
如果我 运行 python awesome-cli configcmd
我收到以下错误(如预期的那样):
Run command: awesome-cli configcmd first-run
Error: Could not open file config.yml: Missing configuration file.
但是,如果我 运行 该命令 python awesome-cli configcmd first-run
我会收到同样的错误,这不是我的目标。显然我应该用这段代码得到那个错误,但那是因为我不知道如何根据被调用的 command/subcommand 添加异常。
我需要在 cli.py
中的 cli
函数中添加什么,这样当(且仅当)用户是 [=37 时,我才不会尝试加载配置文件=]宁configcmd first-run
?任何其他 command/subcommand 都需要此配置文件存在,因此我希望为那些保留检查。
要在执行基于所调用的特定子命令的子命令之前调用一些特定代码,您可以查看 ctx.invoked_subcommand
,例如:
if ctx.invoked_subcommand != 'configcmd':
在您的示例中,您需要检查每个级别的 ctx.invoked_subcommand
,例如:
测试代码:
import sys
import click
from ruamel.yaml import YAML
from pathlib import Path
MYAPP = "AwesomeCLI"
@click.group()
@click.pass_context
def cli(ctx):
"""command line application"""
ctx.ensure_object(dict)
ctx.obj['APPLICATION_NAME'] = MYAPP
ctx.obj['CONFIG_FILEPATH'] = Path(click.get_app_dir(MYAPP), "config.yml")
if ctx.invoked_subcommand != 'configcmd':
load_config(ctx)
@cli.group()
@click.pass_context
def configcmd(ctx):
"""Configuration management for this CLI"""
click.echo("In config")
if ctx.invoked_subcommand != 'first-run':
load_config(ctx)
def load_config(ctx):
yaml = YAML(typ="safe")
try:
config_yml = yaml.load(ctx.obj['CONFIG_FILEPATH'])
except FileNotFoundError:
click.secho("Run command: awesome-cli configcmd first-run",
fg='red')
raise click.FileError(str(ctx.obj['CONFIG_FILEPATH']),
"Missing configuration file.")
ctx.obj['CONFIG'] = yaml.load(config_yml)
@configcmd.command('first-run')
@click.pass_context
def first_run(ctx):
"""Set up CLI configuration."""
click.echo("In first-run")
@configcmd.command('test-cmd')
@click.pass_context
def test_cmd(ctx):
""" This command will not be reachable without config file"""
click.echo("In first-run")
if __name__ == "__main__":
commands = (
'configcmd first-run',
'configcmd test-cmd',
'configcmd --help',
'--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.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> configcmd first-run
In config
In first-run
-----------
> configcmd test-cmd
In config
Run command: awesome-cli configcmd first-run
Error: Could not open file C:\Users\stephen\AppData\Roaming\AwesomeCLI\config.yml: Missing configuration file.
-----------
> configcmd --help
Usage: test.py configcmd [OPTIONS] COMMAND [ARGS]...
Configuration management for this CLI
Options:
--help Show this message and exit.
Commands:
first-run Set up CLI configuration.
test-cmd This command will not be reachable without...
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...
command line application
Options:
--help Show this message and exit.
Commands:
configcmd Configuration management for this CLI
-----------
>
Usage: test.py [OPTIONS] COMMAND [ARGS]...
command line application
Options:
--help Show this message and exit.
Commands:
configcmd Configuration management for this CLI
在正常情况下,我的应用程序会将一组配置值加载到上下文中,这些值将通过 pass_context
传递给子命令。只有一种情况下这不起作用 - 第一次应用程序是 运行 并且尚未设置配置。
我的目标是允许用户 运行 一个子命令并生成适当的配置,以便 CLI 在其余时间正常工作。
我的cli.py
代码:
import sys
import click
from ruamel.yaml import YAML
from pathlib import Path
from commands.config_cmds import configcmd
MYAPP = "AwesomeCLI"
@click.group()
@click.version_option()
@click.pass_context
def cli(ctx):
"""command line application"""
ctx.ensure_object(dict)
ctx.obj['APPLICATION_NAME'] = MYAPP
config_file = Path(click.get_app_dir(ctx.obj[MYAPP])) / "config.yml"
yaml = YAML(typ="safe")
try:
config_yml = yaml.load(config_file)
except FileNotFoundError:
click.secho("Run command: awesome-cli configcmd first-run", fg='red')
raise click.FileError(config_file.name, "Missing configuration file.")
ctx.obj['CONFIG'] = yaml.dump(config_yml)
cli.add_command(configcmd)
我的configcmd
代码:
@click.group()
def configcmd():
"""Manage configuration of this tool
\f
The configuration file is saved in $HOME/.config/awesome-cli
"""
@config.command()
@click.pass_context
def first_run(ctx):
"""
Set up CLI configuration.
"""
api_key = click.prompt("Your API Key")
# More stuff here about saving this file...
如果我 运行 python awesome-cli configcmd
我收到以下错误(如预期的那样):
Run command: awesome-cli configcmd first-run
Error: Could not open file config.yml: Missing configuration file.
但是,如果我 运行 该命令 python awesome-cli configcmd first-run
我会收到同样的错误,这不是我的目标。显然我应该用这段代码得到那个错误,但那是因为我不知道如何根据被调用的 command/subcommand 添加异常。
我需要在 cli.py
中的 cli
函数中添加什么,这样当(且仅当)用户是 [=37 时,我才不会尝试加载配置文件=]宁configcmd first-run
?任何其他 command/subcommand 都需要此配置文件存在,因此我希望为那些保留检查。
要在执行基于所调用的特定子命令的子命令之前调用一些特定代码,您可以查看 ctx.invoked_subcommand
,例如:
if ctx.invoked_subcommand != 'configcmd':
在您的示例中,您需要检查每个级别的 ctx.invoked_subcommand
,例如:
测试代码:
import sys
import click
from ruamel.yaml import YAML
from pathlib import Path
MYAPP = "AwesomeCLI"
@click.group()
@click.pass_context
def cli(ctx):
"""command line application"""
ctx.ensure_object(dict)
ctx.obj['APPLICATION_NAME'] = MYAPP
ctx.obj['CONFIG_FILEPATH'] = Path(click.get_app_dir(MYAPP), "config.yml")
if ctx.invoked_subcommand != 'configcmd':
load_config(ctx)
@cli.group()
@click.pass_context
def configcmd(ctx):
"""Configuration management for this CLI"""
click.echo("In config")
if ctx.invoked_subcommand != 'first-run':
load_config(ctx)
def load_config(ctx):
yaml = YAML(typ="safe")
try:
config_yml = yaml.load(ctx.obj['CONFIG_FILEPATH'])
except FileNotFoundError:
click.secho("Run command: awesome-cli configcmd first-run",
fg='red')
raise click.FileError(str(ctx.obj['CONFIG_FILEPATH']),
"Missing configuration file.")
ctx.obj['CONFIG'] = yaml.load(config_yml)
@configcmd.command('first-run')
@click.pass_context
def first_run(ctx):
"""Set up CLI configuration."""
click.echo("In first-run")
@configcmd.command('test-cmd')
@click.pass_context
def test_cmd(ctx):
""" This command will not be reachable without config file"""
click.echo("In first-run")
if __name__ == "__main__":
commands = (
'configcmd first-run',
'configcmd test-cmd',
'configcmd --help',
'--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.3 (v3.6.3:2c5fed8, Oct 3 2017, 18:11:49) [MSC v.1900 64 bit (AMD64)]
-----------
> configcmd first-run
In config
In first-run
-----------
> configcmd test-cmd
In config
Run command: awesome-cli configcmd first-run
Error: Could not open file C:\Users\stephen\AppData\Roaming\AwesomeCLI\config.yml: Missing configuration file.
-----------
> configcmd --help
Usage: test.py configcmd [OPTIONS] COMMAND [ARGS]...
Configuration management for this CLI
Options:
--help Show this message and exit.
Commands:
first-run Set up CLI configuration.
test-cmd This command will not be reachable without...
-----------
> --help
Usage: test.py [OPTIONS] COMMAND [ARGS]...
command line application
Options:
--help Show this message and exit.
Commands:
configcmd Configuration management for this CLI
-----------
>
Usage: test.py [OPTIONS] COMMAND [ARGS]...
command line application
Options:
--help Show this message and exit.
Commands:
configcmd Configuration management for this CLI