python - 具有多个常用选项的命令使用自定义装饰器进入一个参数
问题描述
我想制作一个模块,使构建共享许多选项的单击命令变得非常简单。这些选项将被提炼成一个传递给命令的对象。作为一个说明性的例子:
from magic import magic_command
import click
@magic_command('Colored')
@click.option('--color')
def cmd(magic, color):
pass
然后,总命令将有许多--magic-...
选项进入magic
传递到的对象cmd
中。我能够使用以下方法实现这一目标:
def magic_command(name):
def decorator(func):
@click.option('--magic-foo')
@click.option('--magic-bar')
def wrapper(magic_foo, magic_bar, **kwargs):
print(f'initializing Magic with {magic_foo} and {magic_bar}')
magic = Magic(magic_foo, magic_bar)
func(magic, **kwargs)
try:
wrapper.__click_params__.extend(func.__click_params__)
except AttributeError:
pass
return click.command(f'{name}-Magic')(wrapper)
return decorator
但是,弄乱了__click_params__
似乎并不是特别干净。
这个问题有点类似于这个问题,但是这种方法不允许我将许多魔法选项浓缩成一个魔法对象。
详细地说,用这种方法我必须做
@magic_command('Colored')
@click.option('--color')
def cmd(magic_foo, magic_bar, color):
magic = Magic(magic_foo, magic_bar)
pass
但这意味着自定义代码需要知道有哪些魔法选项以及如何构建魔法。我想这可以简化使用**kwargs
但仍然 - 理想情况下我只想将一个准备好的magic
对象传递给cmd
.
解决方案
您可以通过构造如下装饰器非常简单地将多个选项提取到单个对象中:
代码:
def magic_options(func):
@click.option('--magic-bar')
@click.option('--magic-foo')
def distill_magic(magic_foo, magic_bar, **kwargs):
kwargs['magic'] = Magic(magic_foo, magic_bar)
func(**kwargs)
return distill_magic
使用装饰器
然后,您可以将装饰器应用于命令函数,例如:
@click.command('Colored-Magic')
@click.option('--color')
@magic_options
def cli(magic, color):
...
它需要应用于裸函数。这是因为返回的函数click.option
已经被点击框架修改了,它不会像你预期的那样工作。
测试代码:
import click
@click.command('Colored-Magic')
@click.option('--color')
@magic_options
def cli(magic, color):
click.echo(str(magic))
click.echo(color)
class Magic(object):
def __init__(self, magic_foo, magic_bar):
self.magic_foo = magic_foo
self.magic_bar = magic_bar
def __str__(self):
return "foo: {} bar: {}".format(self.magic_foo, self.magic_bar)
if __name__ == "__main__":
commands = (
'--magic-foo fooby --magic-bar barbecue',
'--magic-foo fooby',
'--magic-bar barbecue',
'',
'--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)]
-----------
> --magic-foo fooby --magic-bar barbecue
foo: fooby bar: barbecue
-----------
> --magic-foo fooby
foo: fooby bar: None
-----------
> --magic-bar barbecue
foo: None bar: barbecue
-----------
>
foo: None bar: None
-----------
> --help
Usage: test.py [OPTIONS]
Options:
--color TEXT
--magic-bar TEXT
--magic-foo TEXT
--help Show this message and exit.
推荐阅读
- xna - 如何使用定向光理解 HLSL 中的指数阴影映射?
- javascript - 如何在 Cloud Functions 上恢复 Google Cloud Speech API (longRunningRecognize) 超时
- python - 网页抓取 url 中的嵌入链接内容
- java - ImageIcon 找不到照片,路径正确
- php - 将 PHP uniqid 用于文件名是否安全?他们会永远是独一无二的吗?
- html - 图像忽略容器高度
- python - 根据关键字更改列中的特定值
- c# - 列表中有多个相同的元素,如何只显示一次,没有重复?
- javascript - 如何在 Vue 项目中使用 scss 文件和字体
- android - 尝试将 Firebase 存储图像设置为 ImageView Android 时出现问题