Skip to content

Commit ab21233

Browse files
authored
Rewrite second half of options docs (#2848)
Rewrite second half of options docs. Sections moved: - Callbacks and Eager Options from options to advanced - Callbacks for Validation from options to advanced - Auto Envvar Prefix from options to commands-and-groups - Option prompts from options to prompts - Optional prompts from options to prompts - Dynamic Default for Prompts from options to prompts Changes: - Version option added - Flag value rewritten - Feature Switches merged into Flag Value
2 parents f84395c + 8c89a14 commit ab21233

File tree

5 files changed

+293
-349
lines changed

5 files changed

+293
-349
lines changed

docs/advanced.rst

Lines changed: 101 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,107 @@ itself, there are countless patterns that can be implemented by extending
88
Click. This page should give some insight into what can be accomplished.
99

1010
.. contents::
11-
:depth: 1
12-
:local:
11+
:depth: 2
12+
:local:
13+
14+
Callbacks and Eager Options
15+
---------------------------
16+
17+
Sometimes, you want a parameter to completely change the execution flow.
18+
For instance, this is the case when you want to have a ``--version``
19+
parameter that prints out the version and then exits the application.
20+
21+
Note: an actual implementation of a ``--version`` parameter that is
22+
reusable is available in Click as :func:`click.version_option`. The code
23+
here is merely an example of how to implement such a flag.
24+
25+
In such cases, you need two concepts: eager parameters and a callback. An
26+
eager parameter is a parameter that is handled before others, and a
27+
callback is what executes after the parameter is handled. The eagerness
28+
is necessary so that an earlier required parameter does not produce an
29+
error message. For instance, if ``--version`` was not eager and a
30+
parameter ``--foo`` was required and defined before, you would need to
31+
specify it for ``--version`` to work. For more information, see
32+
:ref:`callback-evaluation-order`.
33+
34+
A callback is a function that is invoked with three parameters: the
35+
current :class:`Context`, the current :class:`Parameter`, and the value.
36+
The context provides some useful features such as quitting the
37+
application and gives access to other already processed parameters.
38+
39+
Here's an example for a ``--version`` flag:
40+
41+
.. click:example::
42+
43+
def print_version(ctx, param, value):
44+
if not value or ctx.resilient_parsing:
45+
return
46+
click.echo('Version 1.0')
47+
ctx.exit()
48+
49+
@click.command()
50+
@click.option('--version', is_flag=True, callback=print_version,
51+
expose_value=False, is_eager=True)
52+
def hello():
53+
click.echo('Hello World!')
54+
55+
The `expose_value` parameter prevents the pretty pointless ``version``
56+
parameter from being passed to the callback. If that was not specified, a
57+
boolean would be passed to the `hello` script. The `resilient_parsing`
58+
flag is applied to the context if Click wants to parse the command line
59+
without any destructive behavior that would change the execution flow. In
60+
this case, because we would exit the program, we instead do nothing.
61+
62+
What it looks like:
63+
64+
.. click:run::
65+
66+
invoke(hello)
67+
invoke(hello, args=['--version'])
68+
69+
Callbacks for Validation
70+
------------------------
71+
72+
.. versionchanged:: 2.0
73+
74+
If you want to apply custom validation logic, you can do this in the
75+
parameter callbacks. These callbacks can both modify values as well as
76+
raise errors if the validation does not work. The callback runs after
77+
type conversion. It is called for all sources, including prompts.
78+
79+
In Click 1.0, you can only raise the :exc:`UsageError` but starting with
80+
Click 2.0, you can also raise the :exc:`BadParameter` error, which has the
81+
added advantage that it will automatically format the error message to
82+
also contain the parameter name.
83+
84+
.. click:example::
85+
86+
def validate_rolls(ctx, param, value):
87+
if isinstance(value, tuple):
88+
return value
89+
90+
try:
91+
rolls, _, dice = value.partition("d")
92+
return int(dice), int(rolls)
93+
except ValueError:
94+
raise click.BadParameter("format must be 'NdM'")
95+
96+
@click.command()
97+
@click.option(
98+
"--rolls", type=click.UNPROCESSED, callback=validate_rolls,
99+
default="1d6", prompt=True,
100+
)
101+
def roll(rolls):
102+
sides, times = rolls
103+
click.echo(f"Rolling a {sides}-sided dice {times} time(s)")
104+
105+
.. click:run::
106+
107+
invoke(roll, args=["--rolls=42"])
108+
println()
109+
invoke(roll, args=["--rolls=2d12"])
110+
println()
111+
invoke(roll, input=["42", "2d12"])
13112

14113
.. _custom-groups:
15114

docs/commands-and-groups.rst

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,54 @@ Most examples so far have attached the commands to a group immediately, but comm
216216
Context Object
217217
-------------------
218218
The :class:`Context` object is how commands and groups communicate.
219+
220+
Auto Envvar Prefix
221+
--------------------
222+
Automatically built environment variables are supported for options only. To enable this feature, the ``auto_envvar_prefix`` parameter needs to be passed to the script that is invoked. Each command and parameter is then added as an uppercase underscore-separated variable. If you have a subcommand
223+
called ``run`` taking an option called ``reload`` and the prefix is ``WEB``, then the variable is ``WEB_RUN_RELOAD``.
224+
225+
Example usage:
226+
227+
.. click:example::
228+
229+
@click.command()
230+
@click.option('--username')
231+
def greet(username):
232+
click.echo(f'Hello {username}!')
233+
234+
if __name__ == '__main__':
235+
greet(auto_envvar_prefix='GREETER')
236+
237+
And from the command line:
238+
239+
.. click:run::
240+
241+
invoke(greet, env={'GREETER_USERNAME': 'john'},
242+
auto_envvar_prefix='GREETER')
243+
244+
When using ``auto_envvar_prefix`` with command groups, the command name
245+
needs to be included in the environment variable, between the prefix and
246+
the parameter name, *i.e.* ``PREFIX_COMMAND_VARIABLE``. If you have a
247+
subcommand called ``run-server`` taking an option called ``host`` and
248+
the prefix is ``WEB``, then the variable is ``WEB_RUN_SERVER_HOST``.
249+
250+
.. click:example::
251+
252+
@click.group()
253+
@click.option('--debug/--no-debug')
254+
def cli(debug):
255+
click.echo(f"Debug mode is {'on' if debug else 'off'}")
256+
257+
@cli.command()
258+
@click.option('--username')
259+
def greet(username):
260+
click.echo(f"Hello {username}!")
261+
262+
if __name__ == '__main__':
263+
cli(auto_envvar_prefix='GREETER')
264+
265+
.. click:run::
266+
267+
invoke(cli, args=['greet',],
268+
env={'GREETER_GREET_USERNAME': 'John', 'GREETER_DEBUG': 'false'},
269+
auto_envvar_prefix='GREETER')

docs/option-decorators.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,7 @@ replaced with the :func:`confirmation_option` decorator:
7878
@click.confirmation_option(prompt='Are you sure you want to drop the db?')
7979
def dropdb():
8080
click.echo('Dropped all tables!')
81+
82+
Version Option
83+
----------------
84+
:func:`version_option` adds a ``--version`` option which immediately prints the version number and exits the program.

0 commit comments

Comments
 (0)