|
| 1 | +(parameter-types)= |
| 2 | + |
| 3 | +# Parameter Types |
| 4 | + |
| 5 | +```{currentmodule} click |
| 6 | +``` |
| 7 | + |
| 8 | +When the parameter type is set using `type`, Click will leverage the type to make your life easier, for example adding |
| 9 | +data to your help pages. Most examples are done with options, but types are available to options and arguments. |
| 10 | + |
| 11 | +```{contents} |
| 12 | +--- |
| 13 | +depth: 2 |
| 14 | +local: true |
| 15 | +--- |
| 16 | +``` |
| 17 | + |
| 18 | +## Built-in Types Examples |
| 19 | + |
| 20 | +(choice-opts)= |
| 21 | + |
| 22 | +### Choice |
| 23 | + |
| 24 | +Sometimes, you want to have a parameter be a choice of a list of values. In that case you can use {class}`Choice` type. |
| 25 | +It can be instantiated with a list of valid values. The originally passed choice will be returned, not the str passed on |
| 26 | +the command line. Token normalization functions and `case_sensitive=False` can cause the two to be different but still |
| 27 | +match. {meth}`Choice.normalize_choice` for more info. |
| 28 | + |
| 29 | + |
| 30 | +Example: |
| 31 | + |
| 32 | +```{eval-rst} |
| 33 | +.. click:example:: |
| 34 | +
|
| 35 | + import enum |
| 36 | +
|
| 37 | + class HashType(enum.Enum): |
| 38 | + MD5 = enum.auto() |
| 39 | + SHA1 = enum.auto() |
| 40 | +
|
| 41 | + @click.command() |
| 42 | + @click.option('--hash-type', |
| 43 | + type=click.Choice(HashType, case_sensitive=False)) |
| 44 | + def digest(hash_type: HashType): |
| 45 | + click.echo(hash_type) |
| 46 | +
|
| 47 | +What it looks like: |
| 48 | +
|
| 49 | +.. click:run:: |
| 50 | +
|
| 51 | + invoke(digest, args=['--hash-type=MD5']) |
| 52 | + println() |
| 53 | + invoke(digest, args=['--hash-type=md5']) |
| 54 | + println() |
| 55 | + invoke(digest, args=['--hash-type=foo']) |
| 56 | + println() |
| 57 | + invoke(digest, args=['--help']) |
| 58 | +``` |
| 59 | + |
| 60 | +Any iterable may be passed to {class}`Choice`. If an `Enum` is passed, the names of the enum members will be used as |
| 61 | +valid choices. |
| 62 | + |
| 63 | +Choices work with options that have `multiple=True`. If a `default` value is given with `multiple=True`, it should be a |
| 64 | +list or tuple of valid choices. |
| 65 | + |
| 66 | +Choices should be unique after normalization, see {meth}`Choice.normalize_choice` for more info. |
| 67 | + |
| 68 | +```{versionchanged} 7.1 |
| 69 | +The resulting value from an option will always be one of the originally passed choices |
| 70 | +regardless of `case_sensitive`. |
| 71 | +``` |
| 72 | + |
| 73 | +(ranges)= |
| 74 | + |
| 75 | +### Int and Float Ranges |
| 76 | + |
| 77 | +The {class}`IntRange` type extends the {data}`INT` type to ensure the value is contained in the given range. The |
| 78 | +{class}`FloatRange` type does the same for {data}`FLOAT`. |
| 79 | + |
| 80 | +If `min` or `max` is omitted, that side is *unbounded*. Any value in that direction is accepted. By default, both bounds |
| 81 | +are *closed*, which means the boundary value is included in the accepted range. `min_open` and `max_open` can be used to |
| 82 | +exclude that boundary from the range. |
| 83 | + |
| 84 | +If `clamp` mode is enabled, a value that is outside the range is set to the boundary instead of failing. For example, |
| 85 | +the range `0, 5` would return `5` for the value `10`, or `0` for the value `-1`. When using {class}`FloatRange`, `clamp` |
| 86 | +can only be enabled if both bounds are *closed* (the default). |
| 87 | + |
| 88 | +```{eval-rst} |
| 89 | +.. click:example:: |
| 90 | +
|
| 91 | + @click.command() |
| 92 | + @click.option("--count", type=click.IntRange(0, 20, clamp=True)) |
| 93 | + @click.option("--digit", type=click.IntRange(0, 9)) |
| 94 | + def repeat(count, digit): |
| 95 | + click.echo(str(digit) * count) |
| 96 | +
|
| 97 | +.. click:run:: |
| 98 | +
|
| 99 | + invoke(repeat, args=['--count=100', '--digit=5']) |
| 100 | + invoke(repeat, args=['--count=6', '--digit=12']) |
| 101 | +``` |
| 102 | + |
| 103 | +## Built-in Types Listing |
| 104 | + |
| 105 | +The supported parameter {ref}`click-api-types` are |
| 106 | + |
| 107 | +- `str` / {data}`click.STRING`: The default parameter type which indicates unicode strings. |
| 108 | + |
| 109 | +- `int` / {data}`click.INT`: A parameter that only accepts integers. |
| 110 | + |
| 111 | +- `float` / {data}`click.FLOAT`: A parameter that only accepts floating point values. |
| 112 | + |
| 113 | +- `bool` / {data}`click.BOOL`: A parameter that accepts boolean values. This is automatically used for boolean flags. |
| 114 | + The string values "1", "true", "t", "yes", "y", and "on" convert to `True`. "0", "false", "f", "no", "n", and "off" |
| 115 | + convert to `False`. |
| 116 | + |
| 117 | +- {data}`click.UUID`: A parameter that accepts UUID values. This is not automatically guessed but represented as |
| 118 | + {class}`uuid.UUID`. |
| 119 | + |
| 120 | +```{eval-rst} |
| 121 | +* .. autoclass:: Choice |
| 122 | + :noindex: |
| 123 | +``` |
| 124 | + |
| 125 | +```{eval-rst} |
| 126 | +* .. autoclass:: DateTime |
| 127 | + :noindex: |
| 128 | +``` |
| 129 | + |
| 130 | +```{eval-rst} |
| 131 | +* .. autoclass:: File |
| 132 | + :noindex: |
| 133 | +``` |
| 134 | + |
| 135 | +```{eval-rst} |
| 136 | +* .. autoclass:: FloatRange |
| 137 | + :noindex: |
| 138 | +``` |
| 139 | + |
| 140 | +```{eval-rst} |
| 141 | +* .. autoclass:: IntRange |
| 142 | + :noindex: |
| 143 | +``` |
| 144 | + |
| 145 | +```{eval-rst} |
| 146 | +* .. autoclass:: Path |
| 147 | + :noindex: |
| 148 | +``` |
| 149 | + |
| 150 | +## How to Implement Custom Types |
| 151 | + |
| 152 | +To implement a custom type, you need to subclass the {class}`ParamType` class. For simple cases, passing a Python |
| 153 | +function that fails with a `ValueError` is also supported, though discouraged. Override the {meth}`~ParamType.convert` |
| 154 | +method to convert the value from a string to the correct type. |
| 155 | + |
| 156 | +The following code implements an integer type that accepts hex and octal numbers in addition to normal integers, and |
| 157 | +converts them into regular integers. |
| 158 | + |
| 159 | +```python |
| 160 | +import click |
| 161 | + |
| 162 | +class BasedIntParamType(click.ParamType): |
| 163 | + name = "integer" |
| 164 | + |
| 165 | + def convert(self, value, param, ctx): |
| 166 | + if isinstance(value, int): |
| 167 | + return value |
| 168 | + |
| 169 | + try: |
| 170 | + if value[:2].lower() == "0x": |
| 171 | + return int(value[2:], 16) |
| 172 | + elif value[:1] == "0": |
| 173 | + return int(value, 8) |
| 174 | + return int(value, 10) |
| 175 | + except ValueError: |
| 176 | + self.fail(f"{value!r} is not a valid integer", param, ctx) |
| 177 | + |
| 178 | +BASED_INT = BasedIntParamType() |
| 179 | +``` |
| 180 | + |
| 181 | +The {attr}`~ParamType.name` attribute is optional and is used for documentation. Call {meth}`~ParamType.fail` if |
| 182 | +conversion fails. The `param` and `ctx` arguments may be `None` in some cases such as prompts. |
| 183 | + |
| 184 | +Values from user input or the command line will be strings, but default values and Python arguments may already be the |
| 185 | +correct type. The custom type should check at the top if the value is already valid and pass it through to support those |
| 186 | +cases. |
0 commit comments