307 lines
9 KiB
Python
307 lines
9 KiB
Python
# -*- coding: utf-8 -*-
|
|
import re
|
|
import os
|
|
import click
|
|
import pytest
|
|
|
|
|
|
def test_prefixes(runner):
|
|
@click.command()
|
|
@click.option('++foo', is_flag=True, help='das foo')
|
|
@click.option('--bar', is_flag=True, help='das bar')
|
|
def cli(foo, bar):
|
|
click.echo('foo=%s bar=%s' % (foo, bar))
|
|
|
|
result = runner.invoke(cli, ['++foo', '--bar'])
|
|
assert not result.exception
|
|
assert result.output == 'foo=True bar=True\n'
|
|
|
|
result = runner.invoke(cli, ['--help'])
|
|
assert re.search(r'\+\+foo\s+das foo', result.output) is not None
|
|
assert re.search(r'--bar\s+das bar', result.output) is not None
|
|
|
|
|
|
def test_invalid_option(runner):
|
|
try:
|
|
@click.command()
|
|
@click.option('foo')
|
|
def cli(foo):
|
|
pass
|
|
except TypeError as e:
|
|
assert 'No options defined but a name was passed (foo).' \
|
|
in str(e)
|
|
else:
|
|
assert False, 'Expected a type error because of an invalid option.'
|
|
|
|
|
|
def test_invalid_nargs(runner):
|
|
try:
|
|
@click.command()
|
|
@click.option('--foo', nargs=-1)
|
|
def cli(foo):
|
|
pass
|
|
except TypeError as e:
|
|
assert 'Options cannot have nargs < 0' in str(e)
|
|
else:
|
|
assert False, 'Expected a type error because of an invalid option.'
|
|
|
|
|
|
def test_nargs_tup_composite_mult(runner):
|
|
@click.command()
|
|
@click.option('--item', type=(str, int), multiple=True)
|
|
def copy(item):
|
|
for item in item:
|
|
click.echo('name=%s id=%d' % item)
|
|
|
|
result = runner.invoke(copy, ['--item', 'peter', '1', '--item', 'max', '2'])
|
|
assert not result.exception
|
|
assert result.output.splitlines() == [
|
|
'name=peter id=1',
|
|
'name=max id=2',
|
|
]
|
|
|
|
|
|
def test_counting(runner):
|
|
@click.command()
|
|
@click.option('-v', count=True, help='Verbosity',
|
|
type=click.IntRange(0, 3))
|
|
def cli(v):
|
|
click.echo('verbosity=%d' % v)
|
|
|
|
result = runner.invoke(cli, ['-vvv'])
|
|
assert not result.exception
|
|
assert result.output == 'verbosity=3\n'
|
|
|
|
result = runner.invoke(cli, ['-vvvv'])
|
|
assert result.exception
|
|
assert 'Invalid value for "-v": 4 is not in the valid range of 0 to 3.' \
|
|
in result.output
|
|
|
|
result = runner.invoke(cli, [])
|
|
assert not result.exception
|
|
assert result.output == 'verbosity=0\n'
|
|
|
|
result = runner.invoke(cli, ['--help'])
|
|
assert re.search('-v\s+Verbosity', result.output) is not None
|
|
|
|
|
|
@pytest.mark.parametrize('unknown_flag', ['--foo', '-f'])
|
|
def test_unknown_options(runner, unknown_flag):
|
|
@click.command()
|
|
def cli():
|
|
pass
|
|
|
|
result = runner.invoke(cli, [unknown_flag])
|
|
assert result.exception
|
|
assert 'no such option: {0}'.format(unknown_flag) in result.output
|
|
|
|
|
|
def test_multiple_required(runner):
|
|
@click.command()
|
|
@click.option('-m', '--message', multiple=True, required=True)
|
|
def cli(message):
|
|
click.echo('\n'.join(message))
|
|
|
|
result = runner.invoke(cli, ['-m', 'foo', '-mbar'])
|
|
assert not result.exception
|
|
assert result.output == 'foo\nbar\n'
|
|
|
|
result = runner.invoke(cli, [])
|
|
assert result.exception
|
|
assert 'Error: Missing option "-m" / "--message".' in result.output
|
|
|
|
|
|
def test_multiple_envvar(runner):
|
|
@click.command()
|
|
@click.option('--arg', multiple=True)
|
|
def cmd(arg):
|
|
click.echo('|'.join(arg))
|
|
|
|
result = runner.invoke(cmd, [], auto_envvar_prefix='TEST',
|
|
env={'TEST_ARG': 'foo bar baz'})
|
|
assert not result.exception
|
|
assert result.output == 'foo|bar|baz\n'
|
|
|
|
@click.command()
|
|
@click.option('--arg', multiple=True, envvar='X')
|
|
def cmd(arg):
|
|
click.echo('|'.join(arg))
|
|
|
|
result = runner.invoke(cmd, [], env={'X': 'foo bar baz'})
|
|
assert not result.exception
|
|
assert result.output == 'foo|bar|baz\n'
|
|
|
|
@click.command()
|
|
@click.option('--arg', multiple=True, type=click.Path())
|
|
def cmd(arg):
|
|
click.echo('|'.join(arg))
|
|
|
|
result = runner.invoke(cmd, [], auto_envvar_prefix='TEST',
|
|
env={'TEST_ARG': 'foo%sbar' % os.path.pathsep})
|
|
assert not result.exception
|
|
assert result.output == 'foo|bar\n'
|
|
|
|
|
|
def test_multiple_default_help(runner):
|
|
@click.command()
|
|
@click.option("--arg1", multiple=True, default=('foo', 'bar'),
|
|
show_default=True)
|
|
@click.option("--arg2", multiple=True, default=(1, 2), type=int,
|
|
show_default=True)
|
|
def cmd(arg, arg2):
|
|
pass
|
|
|
|
result = runner.invoke(cmd, ['--help'])
|
|
assert not result.exception
|
|
assert "foo, bar" in result.output
|
|
assert "1, 2" in result.output
|
|
|
|
def test_multiple_default_type(runner):
|
|
@click.command()
|
|
@click.option("--arg1", multiple=True, default=('foo', 'bar'))
|
|
@click.option("--arg2", multiple=True, default=(1, "a"))
|
|
def cmd(arg1, arg2):
|
|
assert all(isinstance(e[0],str) for e in arg1)
|
|
assert all(isinstance(e[1],str) for e in arg1)
|
|
|
|
assert all(isinstance(e[0],int) for e in arg2)
|
|
assert all(isinstance(e[1],str) for e in arg2)
|
|
|
|
result = runner.invoke(cmd, "--arg1 a b --arg1 test 1 --arg2 2 two --arg2 4 four".split())
|
|
assert not result.exception
|
|
|
|
def test_nargs_envvar(runner):
|
|
@click.command()
|
|
@click.option('--arg', nargs=2)
|
|
def cmd(arg):
|
|
click.echo('|'.join(arg))
|
|
|
|
result = runner.invoke(cmd, [], auto_envvar_prefix='TEST',
|
|
env={'TEST_ARG': 'foo bar'})
|
|
assert not result.exception
|
|
assert result.output == 'foo|bar\n'
|
|
|
|
@click.command()
|
|
@click.option('--arg', nargs=2, multiple=True)
|
|
def cmd(arg):
|
|
for item in arg:
|
|
click.echo('|'.join(item))
|
|
|
|
result = runner.invoke(cmd, [], auto_envvar_prefix='TEST',
|
|
env={'TEST_ARG': 'x 1 y 2'})
|
|
assert not result.exception
|
|
assert result.output == 'x|1\ny|2\n'
|
|
|
|
|
|
def test_custom_validation(runner):
|
|
def validate_pos_int(ctx, value):
|
|
if value < 0:
|
|
raise click.BadParameter('Value needs to be positive')
|
|
return value
|
|
|
|
@click.command()
|
|
@click.option('--foo', callback=validate_pos_int, default=1)
|
|
def cmd(foo):
|
|
click.echo(foo)
|
|
|
|
result = runner.invoke(cmd, ['--foo', '-1'])
|
|
assert 'Invalid value for "--foo": Value needs to be positive' \
|
|
in result.output
|
|
|
|
result = runner.invoke(cmd, ['--foo', '42'])
|
|
assert result.output == '42\n'
|
|
|
|
|
|
def test_winstyle_options(runner):
|
|
@click.command()
|
|
@click.option('/debug;/no-debug', help='Enables or disables debug mode.')
|
|
def cmd(debug):
|
|
click.echo(debug)
|
|
|
|
result = runner.invoke(cmd, ['/debug'], help_option_names=['/?'])
|
|
assert result.output == 'True\n'
|
|
result = runner.invoke(cmd, ['/no-debug'], help_option_names=['/?'])
|
|
assert result.output == 'False\n'
|
|
result = runner.invoke(cmd, [], help_option_names=['/?'])
|
|
assert result.output == 'False\n'
|
|
result = runner.invoke(cmd, ['/?'], help_option_names=['/?'])
|
|
assert '/debug; /no-debug Enables or disables debug mode.' in result.output
|
|
assert '/? Show this message and exit.' in result.output
|
|
|
|
|
|
def test_legacy_options(runner):
|
|
@click.command()
|
|
@click.option('-whatever')
|
|
def cmd(whatever):
|
|
click.echo(whatever)
|
|
|
|
result = runner.invoke(cmd, ['-whatever', '42'])
|
|
assert result.output == '42\n'
|
|
result = runner.invoke(cmd, ['-whatever=23'])
|
|
assert result.output == '23\n'
|
|
|
|
|
|
def test_missing_choice(runner):
|
|
@click.command()
|
|
@click.option('--foo', type=click.Choice(['foo', 'bar']),
|
|
required=True)
|
|
def cmd(foo):
|
|
click.echo(foo)
|
|
|
|
result = runner.invoke(cmd)
|
|
assert result.exit_code == 2
|
|
assert 'Error: Missing option "--foo". Choose from foo, bar.' \
|
|
in result.output
|
|
|
|
|
|
def test_multiline_help(runner):
|
|
@click.command()
|
|
@click.option('--foo', help="""
|
|
hello
|
|
|
|
i am
|
|
|
|
multiline
|
|
""")
|
|
def cmd(foo):
|
|
click.echo(foo)
|
|
|
|
result = runner.invoke(cmd, ['--help'])
|
|
assert result.exit_code == 0
|
|
out = result.output.splitlines()
|
|
assert ' --foo TEXT hello' in out
|
|
assert ' i am' in out
|
|
assert ' multiline' in out
|
|
|
|
|
|
def test_argument_custom_class(runner):
|
|
class CustomArgument(click.Argument):
|
|
def get_default(self, ctx):
|
|
'''a dumb override of a default value for testing'''
|
|
return 'I am a default'
|
|
|
|
@click.command()
|
|
@click.argument('testarg', cls=CustomArgument, default='you wont see me')
|
|
def cmd(testarg):
|
|
click.echo(testarg)
|
|
|
|
result = runner.invoke(cmd)
|
|
assert 'I am a default' in result.output
|
|
assert 'you wont see me' not in result.output
|
|
|
|
|
|
def test_option_custom_class(runner):
|
|
class CustomOption(click.Option):
|
|
def get_help_record(self, ctx):
|
|
'''a dumb override of a help text for testing'''
|
|
return ('--help', 'I am a help text')
|
|
|
|
@click.command()
|
|
@click.option('--testoption', cls=CustomOption, help='you wont see me')
|
|
def cmd(testoption):
|
|
click.echo(testoption)
|
|
|
|
result = runner.invoke(cmd, ['--help'])
|
|
assert 'I am a help text' in result.output
|
|
assert 'you wont see me' not in result.output
|