0
# Input Validation
1
2
Comprehensive input validation system with built-in validators for common data types and patterns. The validation framework supports custom error messages, regex patterns, file system validation, and extensible validator chaining for complex input requirements.
3
4
## Capabilities
5
6
### Validation Exception
7
8
Base exception class for all validation errors with message handling.
9
10
```python { .api }
11
class ValidationError(Exception):
12
"""
13
Exception raised during input validation failures.
14
15
Args:
16
message (str): Error message describing the validation failure
17
18
Attributes:
19
message (str): The validation error message
20
error_list (list): List containing this error instance
21
"""
22
23
def __init__(self, message):
24
"""Initialize validation error with message."""
25
```
26
27
### Regular Expression Validator
28
29
Validates input against regular expression patterns with customizable error messages.
30
31
```python { .api }
32
class RegexValidator:
33
"""
34
Validates input against a regular expression pattern.
35
36
Args:
37
regex (str or compiled regex): Regular expression pattern to match
38
message (str): Custom error message (optional)
39
40
Attributes:
41
regex: Compiled regular expression object
42
message (str): Error message displayed on validation failure
43
"""
44
45
def __init__(self, regex=None, message=None):
46
"""Initialize with regex pattern and optional error message."""
47
48
def __call__(self, value):
49
"""
50
Validate input against the regex pattern.
51
52
Args:
53
value (str): Input string to validate
54
55
Returns:
56
str: The validated input value
57
58
Raises:
59
ValidationError: If input doesn't match the pattern
60
"""
61
```
62
63
**Usage Examples:**
64
65
```python
66
from clint.textui.validators import RegexValidator
67
68
# Email validation
69
email_validator = RegexValidator(
70
r'^[^@]+@[^@]+\.[^@]+$',
71
'Please enter a valid email address'
72
)
73
74
# Phone number validation
75
phone_validator = RegexValidator(
76
r'^\+?1?-?\.?\s?\(?([0-9]{3})\)?[-\.\s]?([0-9]{3})[-\.\s]?([0-9]{4})$',
77
'Enter a valid phone number'
78
)
79
80
# Custom pattern validation
81
username_validator = RegexValidator(
82
r'^[a-zA-Z0-9_]{3,20}$',
83
'Username must be 3-20 characters, letters, numbers, underscores only'
84
)
85
86
# Use with prompt
87
from clint.textui import prompt
88
email = prompt.query('Email:', validators=[email_validator])
89
```
90
91
### Path Validator
92
93
Validates that input represents a valid directory path that exists on the filesystem.
94
95
```python { .api }
96
class PathValidator:
97
"""
98
Validates that input is a valid, existing directory path.
99
100
Args:
101
message (str): Custom error message (optional)
102
103
Attributes:
104
message (str): Error message displayed when path is invalid
105
"""
106
107
def __init__(self, message=None):
108
"""Initialize with optional custom error message."""
109
110
def __call__(self, value):
111
"""
112
Validate that input is an existing directory.
113
114
Args:
115
value (str): Path string to validate
116
117
Returns:
118
str: The validated path
119
120
Raises:
121
ValidationError: If path doesn't exist or isn't a directory
122
"""
123
```
124
125
**Usage Examples:**
126
127
```python
128
from clint.textui.validators import PathValidator
129
from clint.textui import prompt
130
131
# Basic path validation
132
path_validator = PathValidator()
133
config_dir = prompt.query('Config directory:', validators=[path_validator])
134
135
# Custom error message
136
path_validator = PathValidator('The specified directory does not exist')
137
backup_dir = prompt.query('Backup directory:', validators=[path_validator])
138
```
139
140
### File Validator
141
142
Validates that input represents a valid file path that exists on the filesystem.
143
144
```python { .api }
145
class FileValidator:
146
"""
147
Validates that input is a valid, existing file path.
148
149
Args:
150
message (str): Custom error message (optional)
151
152
Attributes:
153
message (str): Error message displayed when file is invalid
154
"""
155
156
def __init__(self, message=None):
157
"""Initialize with optional custom error message."""
158
159
def __call__(self, value):
160
"""
161
Validate that input is an existing file.
162
163
Args:
164
value (str): File path string to validate
165
166
Returns:
167
str: The validated file path
168
169
Raises:
170
ValidationError: If file doesn't exist or isn't a file
171
"""
172
```
173
174
**Usage Examples:**
175
176
```python
177
from clint.textui.validators import FileValidator
178
from clint.textui import prompt
179
180
# Configuration file validation
181
config_validator = FileValidator('Configuration file not found')
182
config_file = prompt.query('Config file:', validators=[config_validator])
183
184
# Script validation
185
script_validator = FileValidator()
186
script_path = prompt.query('Script to execute:', validators=[script_validator])
187
```
188
189
### Integer Validator
190
191
Validates that input can be converted to an integer and returns the integer value.
192
193
```python { .api }
194
class IntegerValidator:
195
"""
196
Validates that input is a valid integer and converts it.
197
198
Args:
199
message (str): Custom error message (optional)
200
201
Attributes:
202
message (str): Error message displayed when conversion fails
203
"""
204
205
def __init__(self, message=None):
206
"""Initialize with optional custom error message."""
207
208
def __call__(self, value):
209
"""
210
Validate and convert input to integer.
211
212
Args:
213
value (str): String to convert to integer
214
215
Returns:
216
int: The converted integer value
217
218
Raises:
219
ValidationError: If input cannot be converted to integer
220
"""
221
```
222
223
**Usage Examples:**
224
225
```python
226
from clint.textui.validators import IntegerValidator
227
from clint.textui import prompt
228
229
# Basic integer validation
230
age = prompt.query('Enter your age:', validators=[IntegerValidator()])
231
232
# Custom error message
233
port_validator = IntegerValidator('Port must be a valid number')
234
port = prompt.query('Port number:', validators=[port_validator])
235
236
# Combined with regex for range validation
237
from clint.textui.validators import RegexValidator
238
port_validators = [
239
IntegerValidator('Must be a number'),
240
RegexValidator(r'^([1-9]\d{3,4}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$',
241
'Port must be between 1000-65535')
242
]
243
port = prompt.query('Port:', validators=port_validators)
244
```
245
246
### Option Validator
247
248
Validates that input is one of a predefined set of valid options.
249
250
```python { .api }
251
class OptionValidator:
252
"""
253
Validates that input is in a list of acceptable options.
254
255
Args:
256
options (list): List of valid option values
257
message (str): Custom error message (optional)
258
259
Attributes:
260
options (list): List of acceptable values
261
message (str): Error message displayed when option is invalid
262
"""
263
264
def __init__(self, options, message=None):
265
"""Initialize with list of valid options and optional error message."""
266
267
def __call__(self, value):
268
"""
269
Validate that input is in the options list.
270
271
Args:
272
value (str): Input value to validate
273
274
Returns:
275
str: The validated input value
276
277
Raises:
278
ValidationError: If input is not in the options list
279
"""
280
```
281
282
**Usage Examples:**
283
284
```python
285
from clint.textui.validators import OptionValidator
286
from clint.textui import prompt
287
288
# Environment selection
289
env_validator = OptionValidator(['dev', 'test', 'prod'])
290
environment = prompt.query('Environment (dev/test/prod):', validators=[env_validator])
291
292
# Log level validation
293
log_levels = ['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
294
level_validator = OptionValidator(log_levels, 'Invalid log level')
295
log_level = prompt.query('Log level:', validators=[level_validator])
296
297
# Case variations
298
bool_validator = OptionValidator(['yes', 'no', 'y', 'n', 'true', 'false'])
299
confirm = prompt.query('Confirm:', validators=[bool_validator])
300
```
301
302
## Validator Chaining
303
304
Multiple validators can be used together to create complex validation rules:
305
306
```python
307
from clint.textui.validators import RegexValidator, IntegerValidator
308
from clint.textui import prompt
309
310
# Port number: must be integer AND in valid range
311
port_validators = [
312
IntegerValidator('Must be a valid number'),
313
RegexValidator(r'^([1-9]\d{2,4}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$',
314
'Port must be between 100-65535')
315
]
316
317
port = prompt.query('Port number:', validators=port_validators)
318
319
# Username: regex pattern AND length check
320
username_validators = [
321
RegexValidator(r'^[a-zA-Z0-9_]+$', 'Only letters, numbers, and underscores allowed'),
322
RegexValidator(r'^.{3,20}$', 'Username must be 3-20 characters long')
323
]
324
325
username = prompt.query('Username:', validators=username_validators)
326
```
327
328
## Custom Validators
329
330
Create custom validators by implementing the callable pattern:
331
332
```python
333
from clint.textui.validators import ValidationError
334
335
class PasswordStrengthValidator:
336
def __init__(self, message="Password must be at least 8 characters with numbers"):
337
self.message = message
338
339
def __call__(self, value):
340
if len(value) < 8:
341
raise ValidationError(self.message)
342
if not any(c.isdigit() for c in value):
343
raise ValidationError(self.message)
344
return value
345
346
# Usage
347
from clint.textui import prompt
348
password = prompt.query('Password:', validators=[PasswordStrengthValidator()])
349
```
350
351
## Error Handling
352
353
When validation fails, the validator raises a `ValidationError` with a descriptive message. The prompt system catches these errors, displays the message in yellow text, and re-prompts the user:
354
355
```python
356
# Example of validation failure flow:
357
# User input: "invalid-email"
358
# Validator: RegexValidator(r'^[^@]+@[^@]+\.[^@]+$', 'Enter a valid email')
359
# Output: "Enter a valid email" (in yellow)
360
# Prompt repeats: "Email address: "
361
```