0
# Types and Validation
1
2
Advanced type system with built-in validators, custom type registration, and predefined types for common validation patterns. The jsonargparse type system extends Python's type hints with specialized validators and path types for robust CLI argument validation.
3
4
## Capabilities
5
6
### Type Decorators and Registration
7
8
Functions for registering custom types and extending the type system with validation.
9
10
```python { .api }
11
def register_type(custom_type: Type, serializer: Optional[Callable] = None) -> None:
12
"""
13
Register a custom type for use in parsers.
14
15
Args:
16
custom_type: Type class to register
17
serializer: Optional function to serialize instances of this type
18
"""
19
20
def extend_base_type(base_type: Type, **kwargs) -> Type:
21
"""
22
Extend a base type with additional validation.
23
24
Args:
25
base_type: Base type to extend
26
**kwargs: Validation parameters
27
28
Returns:
29
Type: Extended type with validation
30
"""
31
32
def final(cls: Type) -> Type:
33
"""
34
Mark a class as final (cannot be subclassed).
35
36
Args:
37
cls: Class to mark as final
38
39
Returns:
40
Type: Final class
41
"""
42
43
def is_final_class(cls: Type) -> bool:
44
"""
45
Check if a class is marked as final.
46
47
Args:
48
cls: Class to check
49
50
Returns:
51
bool: True if class is final
52
"""
53
```
54
55
### Restricted Number Types
56
57
Factory functions for creating number types with validation constraints.
58
59
```python { .api }
60
def restricted_number_type(
61
base_type: Union[Type[int], Type[float]],
62
minimum: Optional[Union[int, float]] = None,
63
maximum: Optional[Union[int, float]] = None,
64
exclusive_minimum: Optional[Union[int, float]] = None,
65
exclusive_maximum: Optional[Union[int, float]] = None,
66
multiple_of: Optional[Union[int, float]] = None
67
) -> Type:
68
"""
69
Create a restricted number type with validation.
70
71
Args:
72
base_type: Base numeric type (int or float)
73
minimum: Minimum allowed value (inclusive)
74
maximum: Maximum allowed value (inclusive)
75
exclusive_minimum: Minimum allowed value (exclusive)
76
exclusive_maximum: Maximum allowed value (exclusive)
77
multiple_of: Value must be multiple of this number
78
79
Returns:
80
Type: Restricted number type
81
"""
82
```
83
84
### Restricted String Types
85
86
Factory function for creating string types with validation patterns.
87
88
```python { .api }
89
def restricted_string_type(
90
pattern: Optional[str] = None,
91
min_length: Optional[int] = None,
92
max_length: Optional[int] = None,
93
format: Optional[str] = None
94
) -> Type:
95
"""
96
Create a restricted string type with validation.
97
98
Args:
99
pattern: Regular expression pattern to match
100
min_length: Minimum string length
101
max_length: Maximum string length
102
format: String format validation ('email', 'uri', etc.)
103
104
Returns:
105
Type: Restricted string type
106
"""
107
```
108
109
### Path Type Factory
110
111
Factory function for creating path types with access validation.
112
113
```python { .api }
114
def path_type(mode: str) -> Type:
115
"""
116
Create a path type with specified access mode validation.
117
118
Args:
119
mode: Access mode string (combinations of 'f', 'd', 'r', 'w', 'x', 'c', 'u')
120
121
Returns:
122
Type: Path type with validation
123
"""
124
```
125
126
### Predefined Number Types
127
128
Ready-to-use numeric types with common validation patterns.
129
130
```python { .api }
131
# Positive numbers (> 0)
132
PositiveInt: Type # Positive integer
133
PositiveFloat: Type # Positive float
134
135
# Non-negative numbers (>= 0)
136
NonNegativeInt: Type # Non-negative integer
137
NonNegativeFloat: Type # Non-negative float
138
139
# Unit interval types
140
ClosedUnitInterval: Type # Float in [0, 1]
141
OpenUnitInterval: Type # Float in (0, 1)
142
```
143
144
### Predefined String Types
145
146
Ready-to-use string types with common validation patterns.
147
148
```python { .api }
149
NotEmptyStr: Type # Non-empty string
150
Email: Type # Email address validation
151
SecretStr: Type # Secure string handling (masked in output)
152
```
153
154
### Predefined Path Types
155
156
Ready-to-use path types for common file system access patterns.
157
158
```python { .api }
159
Path_fr: Type # File, readable
160
Path_fc: Type # File, creatable
161
Path_dw: Type # Directory, writable
162
Path_dc: Type # Directory, creatable
163
Path_drw: Type # Directory, readable and writable
164
```
165
166
## Usage Examples
167
168
### Custom Type Registration
169
170
```python
171
from jsonargparse import ArgumentParser, register_type
172
from datetime import datetime
173
174
class DateTimeType:
175
def __init__(self, dt_string: str):
176
self.datetime = datetime.fromisoformat(dt_string)
177
178
def __str__(self):
179
return self.datetime.isoformat()
180
181
# Register custom type
182
register_type(DateTimeType)
183
184
parser = ArgumentParser()
185
parser.add_argument("--start-time", type=DateTimeType, help="Start time in ISO format")
186
187
config = parser.parse_args()
188
print(f"Start time: {config.start_time.datetime}")
189
```
190
191
Usage:
192
```bash
193
python script.py --start-time "2023-01-01T10:30:00"
194
```
195
196
### Restricted Number Validation
197
198
```python
199
from jsonargparse import ArgumentParser, restricted_number_type
200
201
# Create custom numeric types
202
Percentage = restricted_number_type(float, minimum=0.0, maximum=100.0)
203
Port = restricted_number_type(int, minimum=1024, maximum=65535)
204
BatchSize = restricted_number_type(int, minimum=1, multiple_of=8)
205
206
parser = ArgumentParser()
207
parser.add_argument("--accuracy", type=Percentage, help="Model accuracy percentage")
208
parser.add_argument("--port", type=Port, help="Network port number")
209
parser.add_argument("--batch-size", type=BatchSize, help="Training batch size")
210
211
config = parser.parse_args()
212
print(f"Accuracy: {config.accuracy}%")
213
print(f"Port: {config.port}")
214
print(f"Batch size: {config.batch_size}")
215
```
216
217
Usage:
218
```bash
219
python script.py --accuracy 95.5 --port 8080 --batch-size 64
220
python script.py --accuracy 150 # Error: exceeds maximum
221
python script.py --batch-size 33 # Error: not multiple of 8
222
```
223
224
### Restricted String Validation
225
226
```python
227
from jsonargparse import ArgumentParser, restricted_string_type
228
229
# Create string types with validation
230
Username = restricted_string_type(
231
pattern=r"^[a-zA-Z0-9_]{3,20}$",
232
min_length=3,
233
max_length=20
234
)
235
236
IPv4Address = restricted_string_type(
237
pattern=r"^(?:[0-9]{1,3}\.){3}[0-9]{1,3}$"
238
)
239
240
parser = ArgumentParser()
241
parser.add_argument("--username", type=Username, help="Username (alphanumeric, 3-20 chars)")
242
parser.add_argument("--server-ip", type=IPv4Address, help="Server IP address")
243
244
config = parser.parse_args()
245
print(f"Username: {config.username}")
246
print(f"Server IP: {config.server_ip}")
247
```
248
249
### Predefined Types Usage
250
251
```python
252
from jsonargparse import ArgumentParser, PositiveInt, Email, Path_fr, ClosedUnitInterval
253
254
parser = ArgumentParser()
255
parser.add_argument("--workers", type=PositiveInt, help="Number of worker processes")
256
parser.add_argument("--email", type=Email, help="Contact email address")
257
parser.add_argument("--config-file", type=Path_fr, help="Configuration file path")
258
parser.add_argument("--dropout", type=ClosedUnitInterval, help="Dropout rate (0.0-1.0)")
259
260
config = parser.parse_args()
261
print(f"Workers: {config.workers}")
262
print(f"Email: {config.email}")
263
print(f"Config: {config.config_file}")
264
print(f"Dropout: {config.dropout}")
265
```
266
267
Usage:
268
```bash
269
python script.py --workers 4 --email user@example.com --config-file config.yaml --dropout 0.2
270
python script.py --workers -1 # Error: must be positive
271
python script.py --dropout 1.5 # Error: must be in [0, 1]
272
```
273
274
### Path Type Validation
275
276
```python
277
from jsonargparse import ArgumentParser, Path_fr, Path_dw, path_type
278
279
# Use predefined path types
280
parser = ArgumentParser()
281
parser.add_argument("--input", type=Path_fr, help="Input file (must exist and be readable)")
282
parser.add_argument("--output-dir", type=Path_dw, help="Output directory (must be writable)")
283
284
# Create custom path types
285
ExecutableFile = path_type("frx") # File, readable, executable
286
parser.add_argument("--script", type=ExecutableFile, help="Script to execute")
287
288
config = parser.parse_args()
289
print(f"Input: {config.input}")
290
print(f"Output dir: {config.output_dir}")
291
print(f"Script: {config.script}")
292
```
293
294
### Secure String Handling
295
296
```python
297
from jsonargparse import ArgumentParser, SecretStr
298
299
parser = ArgumentParser()
300
parser.add_argument("--password", type=SecretStr, help="Database password")
301
parser.add_argument("--api-key", type=SecretStr, help="API key")
302
303
config = parser.parse_args()
304
305
# SecretStr values are masked in output
306
print(f"Config: {config}") # Shows masked values
307
print(f"Password length: {len(str(config.password))}")
308
309
# Access actual values when needed
310
actual_password = str(config.password)
311
```
312
313
### Type Extension and Composition
314
315
```python
316
from jsonargparse import ArgumentParser, extend_base_type
317
318
# Extend float with custom validation
319
LearningRate = extend_base_type(
320
float,
321
minimum=1e-6,
322
maximum=1.0,
323
description="Learning rate for optimizer"
324
)
325
326
# Use in dataclass
327
from dataclasses import dataclass
328
329
@dataclass
330
class OptimizerConfig:
331
learning_rate: LearningRate = 0.001
332
momentum: ClosedUnitInterval = 0.9
333
weight_decay: NonNegativeFloat = 1e-4
334
335
parser = ArgumentParser()
336
parser.add_class_arguments(OptimizerConfig, "optimizer")
337
338
config = parser.parse_args()
339
opt_config = OptimizerConfig(**config.optimizer.as_dict())
340
print(f"Optimizer: lr={opt_config.learning_rate}, momentum={opt_config.momentum}")
341
```
342
343
### Final Class Validation
344
345
```python
346
from jsonargparse import final, is_final_class
347
348
@final
349
class ProductionConfig:
350
def __init__(self, debug: bool = False):
351
if debug:
352
raise ValueError("Debug mode not allowed in production")
353
self.debug = debug
354
355
# Check if class is final
356
print(f"Is final: {is_final_class(ProductionConfig)}") # True
357
358
# This would raise an error:
359
# class ExtendedConfig(ProductionConfig): # Error: cannot subclass final class
360
# pass
361
```
362
363
## Type Reference
364
365
### Path Mode Characters
366
367
- `f`: Must be a file
368
- `d`: Must be a directory
369
- `r`: Must be readable
370
- `w`: Must be writable
371
- `x`: Must be executable
372
- `c`: File can be created (parent directory writable)
373
- `u`: Path can be a URL
374
375
### Common Predefined Types
376
377
| Type | Description | Example Values |
378
|------|-------------|----------------|
379
| `PositiveInt` | Integer > 0 | 1, 100, 9999 |
380
| `NonNegativeInt` | Integer >= 0 | 0, 1, 100 |
381
| `PositiveFloat` | Float > 0.0 | 0.1, 1.5, 100.0 |
382
| `ClosedUnitInterval` | Float in [0, 1] | 0.0, 0.5, 1.0 |
383
| `OpenUnitInterval` | Float in (0, 1) | 0.1, 0.5, 0.9 |
384
| `NotEmptyStr` | Non-empty string | "hello", "test" |
385
| `Email` | Valid email format | "user@example.com" |
386
| `SecretStr` | Masked string | "[HIDDEN]" in output |
387
388
### Common Path Types
389
390
| Type | Mode | Description |
391
|------|------|-------------|
392
| `Path_fr` | "fr" | Existing readable file |
393
| `Path_fc` | "fc" | File that can be created |
394
| `Path_dw` | "dw" | Writable directory |
395
| `Path_dc` | "dc" | Directory that can be created |
396
| `Path_drw` | "drw" | Readable and writable directory |