123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558 |
- # -*- coding: utf-8 -*-
- import os
- import re
- import pytest
- import click
- from click._compat import text_type
- 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={} bar={}".format(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):
- with pytest.raises(TypeError, match="name was passed"):
- @click.command()
- @click.option("foo")
- def cli(foo):
- pass
- def test_invalid_nargs(runner):
- with pytest.raises(TypeError, match="nargs < 0"):
- @click.command()
- @click.option("--foo", nargs=-1)
- def cli(foo):
- pass
- 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={0[0]} id={0[1]:d}".format(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}".format(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(r"-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: {}".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_empty_envvar(runner):
- @click.command()
- @click.option("--mypath", type=click.Path(exists=True), envvar="MYPATH")
- def cli(mypath):
- click.echo("mypath: {}".format(mypath))
- result = runner.invoke(cli, [], env={"MYPATH": ""})
- assert result.exit_code == 0
- assert result.output == "mypath: None\n"
- 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{}bar".format(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], text_type) for e in arg1)
- assert all(isinstance(e[1], text_type) for e in arg1)
- assert all(isinstance(e[0], int) for e in arg2)
- assert all(isinstance(e[1], text_type) 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_dynamic_default_help_unset(runner):
- @click.command()
- @click.option(
- "--username",
- prompt=True,
- default=lambda: os.environ.get("USER", ""),
- show_default=True,
- )
- def cmd(username):
- print("Hello,", username)
- result = runner.invoke(cmd, ["--help"])
- assert result.exit_code == 0
- assert "--username" in result.output
- assert "lambda" not in result.output
- assert "(dynamic)" in result.output
- def test_dynamic_default_help_text(runner):
- @click.command()
- @click.option(
- "--username",
- prompt=True,
- default=lambda: os.environ.get("USER", ""),
- show_default="current user",
- )
- def cmd(username):
- print("Hello,", username)
- result = runner.invoke(cmd, ["--help"])
- assert result.exit_code == 0
- assert "--username" in result.output
- assert "lambda" not in result.output
- assert "(current user)" in result.output
- def test_toupper_envvar_prefix(runner):
- @click.command()
- @click.option("--arg")
- def cmd(arg):
- click.echo(arg)
- result = runner.invoke(cmd, [], auto_envvar_prefix="test", env={"TEST_ARG": "foo"})
- assert not result.exception
- assert result.output == "foo\n"
- 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_show_envvar(runner):
- @click.command()
- @click.option("--arg1", envvar="ARG1", show_envvar=True)
- def cmd(arg):
- pass
- result = runner.invoke(cmd, ["--help"])
- assert not result.exception
- assert "ARG1" in result.output
- def test_show_envvar_auto_prefix(runner):
- @click.command()
- @click.option("--arg1", show_envvar=True)
- def cmd(arg):
- pass
- result = runner.invoke(cmd, ["--help"], auto_envvar_prefix="TEST")
- assert not result.exception
- assert "TEST_ARG1" in result.output
- def test_show_envvar_auto_prefix_dash_in_command(runner):
- @click.group()
- def cli():
- pass
- @cli.command()
- @click.option("--baz", show_envvar=True)
- def foo_bar(baz):
- pass
- result = runner.invoke(cli, ["foo-bar", "--help"], auto_envvar_prefix="TEST")
- assert not result.exception
- assert "TEST_FOO_BAR_BAZ" in result.output
- def test_custom_validation(runner):
- def validate_pos_int(ctx, param, 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_option_string_cast():
- ctx = click.Context(click.Command(""))
- with pytest.raises(click.MissingParameter) as excinfo:
- click.Option(["-a"], required=True).full_process_value(ctx, None)
- assert str(excinfo.value) == "missing parameter: a"
- 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
- error, separator, choices = result.output.partition("Choose from")
- assert "Error: Missing option '--foo'. " in error
- assert "Choose from" in separator
- assert "foo" in choices
- assert "bar" in choices
- def test_case_insensitive_choice(runner):
- @click.command()
- @click.option("--foo", type=click.Choice(["Orange", "Apple"], case_sensitive=False))
- def cmd(foo):
- click.echo(foo)
- result = runner.invoke(cmd, ["--foo", "apple"])
- assert result.exit_code == 0
- assert result.output == "Apple\n"
- result = runner.invoke(cmd, ["--foo", "oRANGe"])
- assert result.exit_code == 0
- assert result.output == "Orange\n"
- result = runner.invoke(cmd, ["--foo", "Apple"])
- assert result.exit_code == 0
- assert result.output == "Apple\n"
- @click.command()
- @click.option("--foo", type=click.Choice(["Orange", "Apple"]))
- def cmd2(foo):
- click.echo(foo)
- result = runner.invoke(cmd2, ["--foo", "apple"])
- assert result.exit_code == 2
- result = runner.invoke(cmd2, ["--foo", "oRANGe"])
- assert result.exit_code == 2
- result = runner.invoke(cmd2, ["--foo", "Apple"])
- assert result.exit_code == 0
- def test_case_insensitive_choice_returned_exactly(runner):
- @click.command()
- @click.option("--foo", type=click.Choice(["Orange", "Apple"], case_sensitive=False))
- def cmd(foo):
- click.echo(foo)
- result = runner.invoke(cmd, ["--foo", "apple"])
- assert result.exit_code == 0
- assert result.output == "Apple\n"
- def test_option_help_preserve_paragraphs(runner):
- @click.command()
- @click.option(
- "-C",
- "--config",
- type=click.Path(),
- help="""Configuration file to use.
- If not given, the environment variable CONFIG_FILE is consulted
- and used if set. If neither are given, a default configuration
- file is loaded.""",
- )
- def cmd(config):
- pass
- result = runner.invoke(cmd, ["--help"],)
- assert result.exit_code == 0
- assert (
- " -C, --config PATH Configuration file to use.\n"
- "{i}\n"
- "{i}If not given, the environment variable CONFIG_FILE is\n"
- "{i}consulted and used if set. If neither are given, a default\n"
- "{i}configuration file is loaded.".format(i=" " * 21)
- ) in result.output
- 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
- def test_option_custom_class_reusable(runner):
- """Ensure we can reuse a custom class option. See Issue #926"""
- 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")
- # Assign to a variable to re-use the decorator.
- testoption = click.option("--testoption", cls=CustomOption, help="you wont see me")
- @click.command()
- @testoption
- def cmd1(testoption):
- click.echo(testoption)
- @click.command()
- @testoption
- def cmd2(testoption):
- click.echo(testoption)
- # Both of the commands should have the --help option now.
- for cmd in (cmd1, cmd2):
- result = runner.invoke(cmd, ["--help"])
- assert "I am a help text" in result.output
- assert "you wont see me" not in result.output
- def test_bool_flag_with_type(runner):
- @click.command()
- @click.option("--shout/--no-shout", default=False, type=bool)
- def cmd(shout):
- pass
- result = runner.invoke(cmd)
- assert not result.exception
- def test_aliases_for_flags(runner):
- @click.command()
- @click.option("--warnings/--no-warnings", " /-W", default=True)
- def cli(warnings):
- click.echo(warnings)
- result = runner.invoke(cli, ["--warnings"])
- assert result.output == "True\n"
- result = runner.invoke(cli, ["--no-warnings"])
- assert result.output == "False\n"
- result = runner.invoke(cli, ["-W"])
- assert result.output == "False\n"
- @click.command()
- @click.option("--warnings/--no-warnings", "-w", default=True)
- def cli_alt(warnings):
- click.echo(warnings)
- result = runner.invoke(cli_alt, ["--warnings"])
- assert result.output == "True\n"
- result = runner.invoke(cli_alt, ["--no-warnings"])
- assert result.output == "False\n"
- result = runner.invoke(cli_alt, ["-w"])
- assert result.output == "True\n"
- @pytest.mark.parametrize(
- "option_args,expected",
- [
- (["--aggressive", "--all", "-a"], "aggressive"),
- (["--first", "--second", "--third", "-a", "-b", "-c"], "first"),
- (["--apple", "--banana", "--cantaloupe", "-a", "-b", "-c"], "apple"),
- (["--cantaloupe", "--banana", "--apple", "-c", "-b", "-a"], "cantaloupe"),
- (["-a", "-b", "-c"], "a"),
- (["-c", "-b", "-a"], "c"),
- (["-a", "--apple", "-b", "--banana", "-c", "--cantaloupe"], "apple"),
- (["-c", "-a", "--cantaloupe", "-b", "--banana", "--apple"], "cantaloupe"),
- (["--from", "-f", "_from"], "_from"),
- (["--return", "-r", "_ret"], "_ret"),
- ],
- )
- def test_option_names(runner, option_args, expected):
- @click.command()
- @click.option(*option_args, is_flag=True)
- def cmd(**kwargs):
- click.echo(str(kwargs[expected]))
- assert cmd.params[0].name == expected
- for form in option_args:
- if form.startswith("-"):
- result = runner.invoke(cmd, [form])
- assert result.output == "True\n"
|