仅当使用单击时做出选择时才需要和选项
Require and option only if a choice is made when using click
使用click
I know how to define a multiple choice option时。我也知道如何将选项设置为 required 选项。 But, how can I indicate that an option B
is required only if the value of option A
is foo
?
这是一个例子:
import click
@click.command()
@click.option('--output',
type=click.Choice(['stdout', 'file']), default='stdout')
@click.option('--filename', type=click.STRING)
def main(output, filename):
print("output: " + output)
if output == 'file':
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
if __name__ == "__main__":
main()
如果output
选项是stdout
,则不需要filename
。但是,如果用户选择 output
为 file
,则必须提供另一个选项 filename
。点击支持该模式吗?
在函数的开头我可以添加如下内容:
if output == 'file' and filename is None:
raise ValueError('When output is "file", a filename must be provided')
但我很想知道是否有 nicer/cleaner 解决方案。
在这个例子的特殊情况下,我认为一个更简单的方法是去掉 --output
,如果没有指定 --filename
并且如果 --filename
被指定,然后用它代替 stdout
.
但假设这是一个人为的例子,您可以从 click.Option
继承以允许挂接到点击处理中:
自定义 Class:
class OptionRequiredIf(click.Option):
def full_process_value(self, ctx, value):
value = super(OptionRequiredIf, self).full_process_value(ctx, value)
if value is None and ctx.params['output'] == 'file':
msg = 'Required if --output=file'
raise click.MissingParameter(ctx=ctx, param=self, message=msg)
return value
使用自定义 Class:
要使用自定义 class,请将其作为 cls 参数传递给选项装饰器,例如:
@click.option('--filename', type=click.STRING, cls=OptionRequiredIf)
测试代码:
import click
@click.command()
@click.option('--output',
type=click.Choice(['stdout', 'file']), default='stdout')
@click.option('--filename', type=click.STRING, cls=OptionRequiredIf)
def main(output, filename):
print("output: " + output)
if output == 'file':
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
main('--output=file'.split())
结果:
Usage: test.py [OPTIONS]
Error: Missing option "--filename". Required if --output=file
我扩展了 Stephen 的答案,使其更通用:
class OptionRequiredIf(click.Option):
"""
Option is required if the context has `option` set to `value`
"""
def __init__(self, *a, **k):
try:
option = k.pop('option')
value = k.pop('value')
except KeyError:
raise(KeyError("OptionRequiredIf needs the option and value "
"keywords arguments"))
click.Option.__init__(self, *a, **k)
self._option = option
self._value = value
def full_process_value(self, ctx, value):
value = super(OptionRequiredIf, self).full_process_value(ctx, value)
if value is None and ctx.params[self._option] == self._value:
msg = 'Required if --{}={}'.format(self._option, self._value)
raise click.MissingParameter(ctx=ctx, param=self, message=msg)
return value
用法示例:
@click.option('--email', type=click.STRING,
help='Settings for sending emails.',
option='output', value='email', cls=OptionRequiredIf)
我受到了启发answer
使用click
I know how to define a multiple choice option时。我也知道如何将选项设置为 required 选项。 But, how can I indicate that an option B
is required only if the value of option A
is foo
?
这是一个例子:
import click
@click.command()
@click.option('--output',
type=click.Choice(['stdout', 'file']), default='stdout')
@click.option('--filename', type=click.STRING)
def main(output, filename):
print("output: " + output)
if output == 'file':
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
if __name__ == "__main__":
main()
如果output
选项是stdout
,则不需要filename
。但是,如果用户选择 output
为 file
,则必须提供另一个选项 filename
。点击支持该模式吗?
在函数的开头我可以添加如下内容:
if output == 'file' and filename is None:
raise ValueError('When output is "file", a filename must be provided')
但我很想知道是否有 nicer/cleaner 解决方案。
在这个例子的特殊情况下,我认为一个更简单的方法是去掉 --output
,如果没有指定 --filename
并且如果 --filename
被指定,然后用它代替 stdout
.
但假设这是一个人为的例子,您可以从 click.Option
继承以允许挂接到点击处理中:
自定义 Class:
class OptionRequiredIf(click.Option):
def full_process_value(self, ctx, value):
value = super(OptionRequiredIf, self).full_process_value(ctx, value)
if value is None and ctx.params['output'] == 'file':
msg = 'Required if --output=file'
raise click.MissingParameter(ctx=ctx, param=self, message=msg)
return value
使用自定义 Class:
要使用自定义 class,请将其作为 cls 参数传递给选项装饰器,例如:
@click.option('--filename', type=click.STRING, cls=OptionRequiredIf)
测试代码:
import click
@click.command()
@click.option('--output',
type=click.Choice(['stdout', 'file']), default='stdout')
@click.option('--filename', type=click.STRING, cls=OptionRequiredIf)
def main(output, filename):
print("output: " + output)
if output == 'file':
if filename is None:
print("filename must be provided!")
else:
print("filename: " + str(filename))
main('--output=file'.split())
结果:
Usage: test.py [OPTIONS]
Error: Missing option "--filename". Required if --output=file
我扩展了 Stephen 的答案,使其更通用:
class OptionRequiredIf(click.Option):
"""
Option is required if the context has `option` set to `value`
"""
def __init__(self, *a, **k):
try:
option = k.pop('option')
value = k.pop('value')
except KeyError:
raise(KeyError("OptionRequiredIf needs the option and value "
"keywords arguments"))
click.Option.__init__(self, *a, **k)
self._option = option
self._value = value
def full_process_value(self, ctx, value):
value = super(OptionRequiredIf, self).full_process_value(ctx, value)
if value is None and ctx.params[self._option] == self._value:
msg = 'Required if --{}={}'.format(self._option, self._value)
raise click.MissingParameter(ctx=ctx, param=self, message=msg)
return value
用法示例:
@click.option('--email', type=click.STRING,
help='Settings for sending emails.',
option='output', value='email', cls=OptionRequiredIf)
我受到了启发answer