0
# Parameter Types and Validation
1
2
Rich type system for command-line parameter validation and conversion, including built-in types for common data formats and custom type creation. Click's type system ensures user input is properly validated and converted to the expected Python types.
3
4
## Capabilities
5
6
### Base Parameter Type
7
8
Foundation class for all parameter types with validation and conversion capabilities.
9
10
```python { .api }
11
class ParamType:
12
"""
13
Base class for all parameter types.
14
15
Attributes:
16
- name: str, descriptive name of the type
17
- is_composite: bool, whether type expects multiple values
18
- arity: int, number of arguments expected
19
- envvar_list_splitter: str, character to split env var lists
20
"""
21
22
def convert(self, value, param, ctx):
23
"""
24
Convert value to the correct type.
25
26
Parameters:
27
- value: Input value to convert
28
- param: Parameter instance
29
- ctx: Current context
30
31
Returns:
32
Converted value
33
34
Raises:
35
BadParameter: If conversion fails
36
"""
37
38
def fail(self, message, param=None, ctx=None):
39
"""Raise BadParameter with message."""
40
41
def get_metavar(self, param, ctx):
42
"""Get metavar string for help display."""
43
44
def get_missing_message(self, param, ctx):
45
"""Get message for missing required parameter."""
46
47
def shell_complete(self, ctx, param, incomplete):
48
"""Return shell completions for this type."""
49
```
50
51
### Built-in Simple Types
52
53
Basic parameter types for common data formats.
54
55
```python { .api }
56
STRING: StringParamType
57
"""String parameter type that handles encoding and conversion."""
58
59
INT: IntParamType
60
"""Integer parameter type with validation."""
61
62
FLOAT: FloatParamType
63
"""Float parameter type with validation."""
64
65
BOOL: BoolParamType
66
"""Boolean parameter type supporting various string representations."""
67
68
UUID: UUIDParameterType
69
"""UUID parameter type that converts to uuid.UUID objects."""
70
71
UNPROCESSED: UnprocessedParamType
72
"""Unprocessed type that passes values through without conversion."""
73
```
74
75
**Usage Examples:**
76
77
```python
78
@click.command()
79
@click.option('--name', type=click.STRING, help='Your name')
80
@click.option('--age', type=click.INT, help='Your age')
81
@click.option('--height', type=click.FLOAT, help='Height in meters')
82
@click.option('--verbose', type=click.BOOL, help='Enable verbose output')
83
@click.option('--session-id', type=click.UUID, help='Session UUID')
84
def profile(name, age, height, verbose, session_id):
85
"""Update user profile."""
86
click.echo(f'Name: {name} (type: {type(name).__name__})')
87
click.echo(f'Age: {age} (type: {type(age).__name__})')
88
click.echo(f'Height: {height}m (type: {type(height).__name__})')
89
click.echo(f'Verbose: {verbose} (type: {type(verbose).__name__})')
90
click.echo(f'Session: {session_id} (type: {type(session_id).__name__})')
91
```
92
93
### Choice Types
94
95
Restrict parameter values to a predefined set of options.
96
97
```python { .api }
98
class Choice(ParamType):
99
def __init__(self, choices, case_sensitive=True):
100
"""
101
Parameter type that restricts values to a fixed set.
102
103
Parameters:
104
- choices: Sequence of valid choice strings
105
- case_sensitive: Whether matching is case sensitive
106
"""
107
108
def get_metavar(self, param, ctx):
109
"""Return metavar showing available choices."""
110
111
def get_missing_message(self, param, ctx):
112
"""Return message showing available choices."""
113
114
def shell_complete(self, ctx, param, incomplete):
115
"""Complete with matching choices."""
116
```
117
118
**Usage Examples:**
119
120
```python
121
@click.command()
122
@click.option('--log-level',
123
type=click.Choice(['DEBUG', 'INFO', 'WARNING', 'ERROR']),
124
default='INFO',
125
help='Set logging level')
126
@click.option('--format',
127
type=click.Choice(['json', 'xml', 'csv'], case_sensitive=False),
128
help='Output format')
129
def export(log_level, format):
130
"""Export data with specified format."""
131
click.echo(f'Log level: {log_level}')
132
click.echo(f'Format: {format}')
133
```
134
135
### Range Types
136
137
Numeric types with minimum and maximum constraints.
138
139
```python { .api }
140
class IntRange(IntParamType):
141
def __init__(self, min=None, max=None, min_open=False, max_open=False, clamp=False):
142
"""
143
Integer type with range constraints.
144
145
Parameters:
146
- min: Minimum value (inclusive by default)
147
- max: Maximum value (inclusive by default)
148
- min_open: Whether minimum bound is exclusive
149
- max_open: Whether maximum bound is exclusive
150
- clamp: Clamp out-of-range values instead of failing
151
"""
152
153
class FloatRange(FloatParamType):
154
def __init__(self, min=None, max=None, min_open=False, max_open=False, clamp=False):
155
"""
156
Float type with range constraints.
157
158
Parameters:
159
- min: Minimum value (inclusive by default)
160
- max: Maximum value (inclusive by default)
161
- min_open: Whether minimum bound is exclusive
162
- max_open: Whether maximum bound is exclusive
163
- clamp: Clamp out-of-range values instead of failing
164
"""
165
```
166
167
**Usage Examples:**
168
169
```python
170
@click.command()
171
@click.option('--port', type=click.IntRange(1, 65535),
172
help='Port number (1-65535)')
173
@click.option('--timeout', type=click.FloatRange(0.1, 300.0),
174
default=30.0, help='Timeout in seconds')
175
@click.option('--percentage', type=click.IntRange(0, 100, clamp=True),
176
help='Percentage (clamped to 0-100)')
177
def connect(port, timeout, percentage):
178
"""Connect with validation."""
179
click.echo(f'Port: {port}')
180
click.echo(f'Timeout: {timeout}s')
181
click.echo(f'Percentage: {percentage}%')
182
```
183
184
### Date and Time Types
185
186
Handle date and time parsing with multiple format support.
187
188
```python { .api }
189
class DateTime(ParamType):
190
def __init__(self, formats=None):
191
"""
192
DateTime parameter type.
193
194
Parameters:
195
- formats: List of strptime format strings to try
196
(defaults to common ISO formats)
197
"""
198
199
def get_metavar(self, param, ctx):
200
"""Return metavar showing expected formats."""
201
```
202
203
**Usage Examples:**
204
205
```python
206
@click.command()
207
@click.option('--start-date',
208
type=click.DateTime(['%Y-%m-%d', '%m/%d/%Y']),
209
help='Start date (YYYY-MM-DD or MM/DD/YYYY)')
210
@click.option('--timestamp',
211
type=click.DateTime(['%Y-%m-%d %H:%M:%S']),
212
help='Timestamp (YYYY-MM-DD HH:MM:SS)')
213
def schedule(start_date, timestamp):
214
"""Schedule operation."""
215
click.echo(f'Start date: {start_date}')
216
click.echo(f'Timestamp: {timestamp}')
217
click.echo(f'Date type: {type(start_date).__name__}')
218
```
219
220
### File and Path Types
221
222
Handle file operations and path validation with comprehensive options.
223
224
```python { .api }
225
class File(ParamType):
226
def __init__(self, mode="r", encoding=None, errors="strict", lazy=None, atomic=False):
227
"""
228
File parameter type for reading/writing files.
229
230
Parameters:
231
- mode: File open mode ('r', 'w', 'a', 'rb', 'wb', etc.)
232
- encoding: Text encoding (None for binary modes)
233
- errors: Error handling strategy ('strict', 'ignore', 'replace')
234
- lazy: Open file lazily on first access
235
- atomic: Write to temporary file then move (for write modes)
236
"""
237
238
class Path(ParamType):
239
def __init__(self, exists=False, file_okay=True, dir_okay=True,
240
writable=False, readable=True, resolve_path=False,
241
allow_dash=False, path_type=None, executable=False):
242
"""
243
Path parameter type with validation.
244
245
Parameters:
246
- exists: Path must exist
247
- file_okay: Allow files
248
- dir_okay: Allow directories
249
- writable: Path must be writable
250
- readable: Path must be readable
251
- resolve_path: Make absolute and resolve symlinks
252
- allow_dash: Allow '-' for stdin/stdout
253
- path_type: Convert to this type (str, bytes, pathlib.Path)
254
- executable: Path must be executable
255
"""
256
257
def shell_complete(self, ctx, param, incomplete):
258
"""Provide path completion."""
259
```
260
261
**Usage Examples:**
262
263
```python
264
@click.command()
265
@click.option('--input', type=click.File('r'), help='Input file')
266
@click.option('--output', type=click.File('w'), help='Output file')
267
@click.option('--config',
268
type=click.Path(exists=True, readable=True),
269
help='Configuration file path')
270
@click.option('--log-dir',
271
type=click.Path(exists=True, dir_okay=True, file_okay=False, writable=True),
272
help='Log directory')
273
def process(input, output, config, log_dir):
274
"""Process files."""
275
content = input.read()
276
output.write(f'Processed: {content}')
277
click.echo(f'Config: {config}')
278
click.echo(f'Log directory: {log_dir}')
279
280
# Using pathlib.Path
281
from pathlib import Path
282
283
@click.command()
284
@click.option('--workspace',
285
type=click.Path(path_type=Path, exists=True, dir_okay=True),
286
help='Workspace directory')
287
def workspace_cmd(workspace):
288
"""Work with pathlib.Path objects."""
289
click.echo(f'Workspace: {workspace}')
290
click.echo(f'Absolute path: {workspace.absolute()}')
291
click.echo(f'Is directory: {workspace.is_dir()}')
292
```
293
294
### Composite Types
295
296
Handle multiple values and complex data structures.
297
298
```python { .api }
299
class Tuple(ParamType):
300
def __init__(self, types):
301
"""
302
Tuple parameter type for multiple typed values.
303
304
Parameters:
305
- types: Sequence of ParamType instances for each tuple element
306
307
Attributes:
308
- is_composite: True
309
- arity: Length of types sequence
310
"""
311
312
def convert(self, value, param, ctx):
313
"""Convert each tuple element with corresponding type."""
314
```
315
316
**Usage Examples:**
317
318
```python
319
@click.command()
320
@click.option('--point',
321
type=click.Tuple([click.FLOAT, click.FLOAT]),
322
help='2D coordinate (x y)')
323
@click.option('--range',
324
type=click.Tuple([click.INT, click.INT, click.STRING]),
325
help='Range specification (start end unit)')
326
def geometry(point, range):
327
"""Work with tuples."""
328
if point:
329
x, y = point
330
click.echo(f'Point: ({x}, {y})')
331
332
if range:
333
start, end, unit = range
334
click.echo(f'Range: {start}-{end} {unit}')
335
```
336
337
### Custom Parameter Types
338
339
Create custom parameter types for specialized validation and conversion.
340
341
```python
342
# Custom email type
343
class EmailType(click.ParamType):
344
name = "email"
345
346
def convert(self, value, param, ctx):
347
import re
348
if not re.match(r'^[^@]+@[^@]+\.[^@]+$', value):
349
self.fail(f'{value} is not a valid email address', param, ctx)
350
return value
351
352
EMAIL = EmailType()
353
354
# Custom JSON type
355
class JSONType(click.ParamType):
356
name = "json"
357
358
def convert(self, value, param, ctx):
359
import json
360
try:
361
return json.loads(value)
362
except json.JSONDecodeError as e:
363
self.fail(f'Invalid JSON: {e}', param, ctx)
364
365
JSON = JSONType()
366
367
@click.command()
368
@click.option('--email', type=EMAIL, help='Email address')
369
@click.option('--config', type=JSON, help='JSON configuration')
370
def custom_types(email, config):
371
"""Example using custom types."""
372
click.echo(f'Email: {email}')
373
click.echo(f'Config: {config}')
374
```