-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Description
TL;DR
click.testing.CliRunner.invoke
and click.Context
signatures shares a common color
parameter.
So when the former call the later via click.BaseCommand.main
, that command's main()
cannot get a color
parameter in its **extra
(because it has been consumed by click.testing.CliRunner.invoke
).
Description
I'm in the middle of developing a set of extensions for Click under the name click-extra
. It involves a lot of colouring helpers. In my testing suite I need to simulate a command that will end up having its default context's color
property initialized to user's liking.
For that I need the **extra
dictionnary of click.testing.CliRunner.invoke
to contain a "color": "my_custom_value"
item. The problem is that invoke()
method redefine itself the color
property. Which means its signature consume my default value and is never appended to the **extra
dictionary of the original command's main()
call.
Current behavior
The current implementation allows for the invoke
command to specify the color rendering of the output:
import click
from click.testing import CliRunner
runner = CliRunner()
@click.command()
@click.pass_context
def my_cli(ctx):
click.echo(click.style("It works!", fg="blue"))
click.echo(f"Context.color = {ctx.color!r}")
def test_vanilla_invokation():
# Default invokation strip colors, no context influence.
result = runner.invoke(my_cli)
assert result.exit_code == 0
assert "It works!" in result.output
assert "Context.color = None" in result.output
# Force results to strip colors, no context influence.
result = runner.invoke(my_cli, color=False)
assert result.exit_code == 0
assert "It works!" in result.output
assert "Context.color = None" in result.output
# Force results to keep colors, no context influence.
result = runner.invoke(my_cli, color=True)
assert result.exit_code == 0
assert "\x1b[34mIt works!\x1b[0m" in result.output
assert "Context.color = None" in result.output
Notice how it does not have any influence on the command's context.
Expected behavior
I'm looking to have an influence on the command context. Here is what I expect invoke()
would allow me to do:
def test_context_color_initialization():
extra = {"color": "my_custom_value"}
# Default invokation strip colors, no context influence.
result = runner.invoke(my_cli, **extra)
assert result.exit_code == 0
assert "It works!" in result.output
assert "Context.color = None" in result.output
# Force results to strip colors, no context influence.
result = runner.invoke(my_cli, color=False, **extra)
assert result.exit_code == 0
assert "It works!" in result.output
assert "Context.color = 'my_custom_value'" in result.output
# Force results to keep colors, no context influence.
result = runner.invoke(my_cli, color=True, **extra)
assert result.exit_code == 0
assert "\x1b[34mIt works!\x1b[0m" in result.output
assert "Context.color = 'my_custom_value'" in result.output
Of course it doesn't work as invoke()
ends up with 2 values for color
, and is thus unable to pass one of them in the form of my_cli.main(color="my_custom_value")
for context instanciation.
Environment
-
Python version:
$ python Python 3.9.7 (default, Oct 13 2021, 06:45:31) [Clang 13.0.0 (clang-1300.0.29.3)] on darwin
-
Click version:
>>> import click >>> click.__version__ '8.0.3'