123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245 |
- import sys
- import pytest
- import click
- def debug():
- click.echo(
- f"{sys._getframe(1).f_code.co_name}"
- f"={'|'.join(click.get_current_context().args)}"
- )
- def test_basic_chaining(runner):
- @click.group(chain=True)
- def cli():
- pass
- @cli.command("sdist")
- def sdist():
- click.echo("sdist called")
- @cli.command("bdist")
- def bdist():
- click.echo("bdist called")
- result = runner.invoke(cli, ["bdist", "sdist", "bdist"])
- assert not result.exception
- assert result.output.splitlines() == [
- "bdist called",
- "sdist called",
- "bdist called",
- ]
- @pytest.mark.parametrize(
- ("args", "expect"),
- [
- (["--help"], "COMMAND1 [ARGS]... [COMMAND2 [ARGS]...]..."),
- (["--help"], "ROOT HELP"),
- (["sdist", "--help"], "SDIST HELP"),
- (["bdist", "--help"], "BDIST HELP"),
- (["bdist", "sdist", "--help"], "SDIST HELP"),
- ],
- )
- def test_chaining_help(runner, args, expect):
- @click.group(chain=True)
- def cli():
- """ROOT HELP"""
- pass
- @cli.command("sdist")
- def sdist():
- """SDIST HELP"""
- click.echo("sdist called")
- @cli.command("bdist")
- def bdist():
- """BDIST HELP"""
- click.echo("bdist called")
- result = runner.invoke(cli, args)
- assert not result.exception
- assert expect in result.output
- def test_chaining_with_options(runner):
- @click.group(chain=True)
- def cli():
- pass
- @cli.command("sdist")
- @click.option("--format")
- def sdist(format):
- click.echo(f"sdist called {format}")
- @cli.command("bdist")
- @click.option("--format")
- def bdist(format):
- click.echo(f"bdist called {format}")
- result = runner.invoke(cli, ["bdist", "--format=1", "sdist", "--format=2"])
- assert not result.exception
- assert result.output.splitlines() == ["bdist called 1", "sdist called 2"]
- @pytest.mark.parametrize(("chain", "expect"), [(False, "1"), (True, "[]")])
- def test_no_command_result_callback(runner, chain, expect):
- """When a group has ``invoke_without_command=True``, the result
- callback is always invoked. A regular group invokes it with
- its return value, a chained group with ``[]``.
- """
- @click.group(invoke_without_command=True, chain=chain)
- def cli():
- return 1
- @cli.result_callback()
- def process_result(result):
- click.echo(result, nl=False)
- result = runner.invoke(cli, [])
- assert result.output == expect
- def test_chaining_with_arguments(runner):
- @click.group(chain=True)
- def cli():
- pass
- @cli.command("sdist")
- @click.argument("format")
- def sdist(format):
- click.echo(f"sdist called {format}")
- @cli.command("bdist")
- @click.argument("format")
- def bdist(format):
- click.echo(f"bdist called {format}")
- result = runner.invoke(cli, ["bdist", "1", "sdist", "2"])
- assert not result.exception
- assert result.output.splitlines() == ["bdist called 1", "sdist called 2"]
- @pytest.mark.parametrize(
- ("args", "input", "expect"),
- [
- (["-f", "-"], "foo\nbar", ["foo", "bar"]),
- (["-f", "-", "strip"], "foo \n bar", ["foo", "bar"]),
- (["-f", "-", "strip", "uppercase"], "foo \n bar", ["FOO", "BAR"]),
- ],
- )
- def test_pipeline(runner, args, input, expect):
- @click.group(chain=True, invoke_without_command=True)
- @click.option("-f", type=click.File("r"))
- def cli(f):
- pass
- @cli.result_callback()
- def process_pipeline(processors, f):
- iterator = (x.rstrip("\r\n") for x in f)
- for processor in processors:
- iterator = processor(iterator)
- for item in iterator:
- click.echo(item)
- @cli.command("uppercase")
- def make_uppercase():
- def processor(iterator):
- for line in iterator:
- yield line.upper()
- return processor
- @cli.command("strip")
- def make_strip():
- def processor(iterator):
- for line in iterator:
- yield line.strip()
- return processor
- result = runner.invoke(cli, args, input=input)
- assert not result.exception
- assert result.output.splitlines() == expect
- def test_args_and_chain(runner):
- @click.group(chain=True)
- def cli():
- debug()
- @cli.command()
- def a():
- debug()
- @cli.command()
- def b():
- debug()
- @cli.command()
- def c():
- debug()
- result = runner.invoke(cli, ["a", "b", "c"])
- assert not result.exception
- assert result.output.splitlines() == ["cli=", "a=", "b=", "c="]
- def test_multicommand_arg_behavior(runner):
- with pytest.raises(RuntimeError):
- @click.group(chain=True)
- @click.argument("forbidden", required=False)
- def bad_cli():
- pass
- with pytest.raises(RuntimeError):
- @click.group(chain=True)
- @click.argument("forbidden", nargs=-1)
- def bad_cli2():
- pass
- @click.group(chain=True)
- @click.argument("arg")
- def cli(arg):
- click.echo(f"cli:{arg}")
- @cli.command()
- def a():
- click.echo("a")
- result = runner.invoke(cli, ["foo", "a"])
- assert not result.exception
- assert result.output.splitlines() == ["cli:foo", "a"]
- @pytest.mark.xfail
- def test_multicommand_chaining(runner):
- @click.group(chain=True)
- def cli():
- debug()
- @cli.group()
- def l1a():
- debug()
- @l1a.command()
- def l2a():
- debug()
- @l1a.command()
- def l2b():
- debug()
- @cli.command()
- def l1b():
- debug()
- result = runner.invoke(cli, ["l1a", "l2a", "l1b"])
- assert not result.exception
- assert result.output.splitlines() == ["cli=", "l1a=", "l2a=", "l1b="]
|