Skip to content

Commit 30aca6b

Browse files
committed
Document the interaction between default and flag_value
1 parent dbcea3f commit 30aca6b

File tree

1 file changed

+70
-5
lines changed

1 file changed

+70
-5
lines changed

docs/options.md

Lines changed: 70 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -341,12 +341,13 @@ To have a flag pass a value to the decorated function set `flag_value`. This aut
341341
invoke(info)
342342
```
343343

344-
````{note}
345-
The `default` value is given to the decorated function as-is. So if you set `default=None`, the value passed to the function is the `None` Python value. Same for any other type.
344+
### How `default` and `flag_value` interact
346345

347-
But there is a special case for flags. If a flag has a `flag_value`, then setting `default=True` is interpreted as *the flag should be activated by default*. So instead of the decorated function receiving the `True` Python value, it will receive the `flag_value`.
346+
The `default` value is given to the underlying function as-is. So if you set `default=None`, the function receives `None`. Same for any other type.
348347

349-
Which means, in example above, this option:
348+
But there is a special case for **non-boolean** flags: if a flag has a non-boolean `flag_value` (like a string or a class), then `default=True` is interpreted as *the flag should be activated by default*. The function receives the `flag_value`, not the Python `True`.
349+
350+
Which means, in the example above, this option:
350351

351352
```python
352353
@click.option('--upper', 'transformation', flag_value='upper', default=True)
@@ -358,9 +359,73 @@ is equivalent to:
358359
@click.option('--upper', 'transformation', flag_value='upper', default='upper')
359360
```
360361

361-
Because the two are equivalent, it is recommended to always set `default` to the actual value you want to pass and avoid using the special `True` case. This makes the code more explicit and predictable.
362+
Because the two are equivalent, it is recommended to always use the second form and set `default` to the actual value you want. This makes code more explicit and predictable.
363+
364+
This special case does **not** apply to boolean flags (where `flag_value` is `True` or `False`). For boolean flags, `default=True` is the literal Python value `True`.
365+
366+
The tables below show the value received by the function for each combination of `default`, `flag_value`, and whether the flag was passed on the command line.
367+
368+
#### Boolean flags (`is_flag=True`, boolean `flag_value`)
369+
370+
These are flags where `flag_value` is `True` or `False`. The `default` value is always passed through literally without any special substitution.
371+
372+
| `default` | `flag_value` | Not passed | `--flag` passed |
373+
|-----------|--------------|------------|-----------------|
374+
| *(unset)* | *(unset)* | `False` | `True` |
375+
| `True` | *(unset)* | `True` | `True` |
376+
| `False` | *(unset)* | `False` | `True` |
377+
| `None` | *(unset)* | `None` | `True` |
378+
| `True` | `True` | `True` | `True` |
379+
| `True` | `False` | `True` | `False` |
380+
| `False` | `True` | `False` | `True` |
381+
| `False` | `False` | `False` | `False` |
382+
| `None` | `True` | `None` | `True` |
383+
| `None` | `False` | `None` | `False` |
384+
385+
````{tip}
386+
For a negative flag that defaults to off, prefer the explicit pair form `--with-xyz/--without-xyz` over the single-flag `flag_value=False, default=True`:
387+
388+
```python
389+
@click.option('--with-xyz/--without-xyz', 'enable_xyz', default=True)
390+
```
362391
````
363392

393+
#### Boolean flag pairs (`--flag/--no-flag`)
394+
395+
These use secondary option names to provide both an on and off switch. The `default` value is always literal.
396+
397+
| `default` | Not passed | `--flag` | `--no-flag` |
398+
|-----------|------------|----------|-------------|
399+
| *(unset)* | `False` | `True` | `False` |
400+
| `True` | `True` | `True` | `False` |
401+
| `False` | `False` | `True` | `False` |
402+
| `None` | `None` | `True` | `False` |
403+
404+
#### Non-boolean feature switches (`flag_value` is a string, class, etc.)
405+
406+
For these flags, `default=True` is a **special case**: it means "activate this flag by default" and resolves to the `flag_value`. All other `default` values are passed through literally.
407+
408+
| `default` | `flag_value` | Not passed | `--flag` passed |
409+
|------------|--------------|-------------|-----------------|
410+
| *(unset)* | `"upper"` | `None` | `"upper"` |
411+
| `True` | `"upper"` | `"upper"`¹ | `"upper"` |
412+
| `"lower"` | `"upper"` | `"lower"` | `"upper"` |
413+
| `None` | `"upper"` | `None` | `"upper"` |
414+
415+
```{hint}
416+
¹: `default=True` is substituted with `flag_value`.
417+
```
418+
419+
#### Feature switch groups (multiple flags sharing one variable)
420+
421+
When multiple `flag_value` options target the same parameter name, `default=True` on one of them marks it as the default choice.
422+
423+
| Definition | Not passed | `--upper` | `--lower` |
424+
|--------------------------------------------------------|------------|-----------|-----------|
425+
| `--upper` with `flag_value='upper'`, `default=True` | `"upper"` | `"upper"` | `"lower"` |
426+
| `--upper` with `flag_value='upper'`, `default='upper'` | `"upper"` | `"upper"` | `"lower"` |
427+
| Both without `default` | `None` | `"upper"` | `"lower"` |
428+
364429
## Values from Environment Variables
365430

366431
To pass in a value from a specific environment variable use `envvar`.

0 commit comments

Comments
 (0)