0
# Type Coercion & Conversion
1
2
Type conversion and coercion with error handling, truth value validation, and human-readable boolean conversion. These validators handle type transformations and validate type-specific conditions.
3
4
## Capabilities
5
6
### Type Coercion
7
8
Convert values to specified types with graceful error handling.
9
10
```python { .api }
11
class Coerce:
12
def __init__(self, type, msg=None):
13
"""
14
Convert value to specified type.
15
16
Parameters:
17
- type: Target type to convert to (int, float, str, etc.)
18
- msg: Custom error message if coercion fails
19
20
Returns:
21
Value converted to target type
22
23
Raises:
24
CoerceInvalid: If conversion fails (ValueError/TypeError from type constructor)
25
"""
26
```
27
28
**Usage Examples:**
29
30
```python
31
from voluptuous import Schema, Coerce, All, Range
32
33
# Convert strings to numbers
34
numeric_schema = Schema({
35
'age': Coerce(int), # "25" -> 25
36
'price': Coerce(float), # "19.99" -> 19.99
37
'active': Coerce(bool), # "true" -> True, "false" -> False
38
})
39
40
# Combined with validation
41
validated_age = Schema(All(
42
Coerce(int), # Convert to int first
43
Range(min=0, max=150), # Then validate range
44
))
45
46
# Custom types
47
from decimal import Decimal
48
decimal_price = Schema(All(
49
Coerce(Decimal), # Convert to Decimal
50
lambda x: x >= 0, # Validate non-negative
51
))
52
```
53
54
### Boolean Conversion
55
56
Convert human-readable values to boolean with comprehensive string recognition.
57
58
```python { .api }
59
def Boolean(v):
60
"""
61
Convert human-readable values to boolean.
62
63
Parameters:
64
- v: Value to convert to boolean
65
66
Accepted truthy values:
67
'1', 'true', 'yes', 'on', 'enable', 1, True (case-insensitive for strings)
68
69
Accepted falsy values:
70
'0', 'false', 'no', 'off', 'disable', 0, False (case-insensitive for strings)
71
72
Returns:
73
True or False
74
75
Raises:
76
BooleanInvalid: If value cannot be converted to boolean
77
"""
78
```
79
80
**Usage Examples:**
81
82
```python
83
from voluptuous import Schema, Boolean
84
85
# Flexible boolean conversion
86
settings_schema = Schema({
87
'debug': Boolean, # Accepts 'true', 'yes', '1', True, etc.
88
'logging': Boolean, # Accepts 'false', 'no', '0', False, etc.
89
'ssl_enabled': Boolean,
90
})
91
92
# Valid inputs:
93
settings_schema({
94
'debug': 'true', # -> True
95
'logging': 'no', # -> False
96
'ssl_enabled': 1, # -> True
97
})
98
99
settings_schema({
100
'debug': 'YES', # -> True (case-insensitive)
101
'logging': 'disable', # -> False
102
'ssl_enabled': '0', # -> False
103
})
104
```
105
106
### Truth Value Validation
107
108
Validate whether values are truthy or falsy in Python's sense.
109
110
```python { .api }
111
def IsTrue(v):
112
"""
113
Assert value is truthy in Python sense.
114
115
Parameters:
116
- v: Value to test for truthiness
117
118
Returns:
119
Original value if truthy
120
121
Raises:
122
TrueInvalid: If value is falsy (False, None, 0, '', [], {}, etc.)
123
"""
124
125
def IsFalse(v):
126
"""
127
Assert value is falsy in Python sense.
128
129
Parameters:
130
- v: Value to test for falsiness
131
132
Returns:
133
Original value if falsy
134
135
Raises:
136
FalseInvalid: If value is truthy
137
"""
138
```
139
140
**Usage Examples:**
141
142
```python
143
from voluptuous import Schema, IsTrue, IsFalse, Any
144
145
# Validate required fields are not empty
146
data_schema = Schema({
147
'name': IsTrue, # Must be non-empty string
148
'items': IsTrue, # Must be non-empty list
149
'settings': IsTrue, # Must be non-empty dict
150
})
151
152
# Valid data
153
data_schema({
154
'name': 'John', # Truthy string
155
'items': [1, 2, 3], # Non-empty list
156
'settings': {'debug': True}, # Non-empty dict
157
})
158
159
# Invalid data would fail:
160
# data_schema({'name': '', 'items': [], 'settings': {}}) # All falsy
161
162
# Validate disabled features
163
feature_schema = Schema({
164
'legacy_mode': IsFalse, # Must be disabled/falsy
165
'deprecated_api': IsFalse, # Must be disabled/falsy
166
})
167
168
# Accept various ways of expressing "disabled"
169
feature_schema({
170
'legacy_mode': False, # Explicitly False
171
'deprecated_api': None, # None is falsy
172
})
173
```
174
175
### Truth Function Decorator
176
177
Convert arbitrary boolean functions into validators.
178
179
```python { .api }
180
def truth(f):
181
"""
182
Decorator to convert truth functions into validators.
183
184
Parameters:
185
- f: Function that returns True/False for validation
186
187
Returns:
188
Validator function that raises ValueError if f returns False
189
190
Usage:
191
Decorate any function that returns boolean to create a validator
192
"""
193
```
194
195
**Usage Examples:**
196
197
```python
198
from voluptuous import Schema, truth
199
import os.path
200
201
# Convert existing boolean functions to validators
202
@truth
203
def is_file(path):
204
return os.path.isfile(path)
205
206
@truth
207
def is_even(n):
208
return n % 2 == 0
209
210
@truth
211
def is_valid_email_domain(email):
212
return email.split('@')[1] in ['company.com', 'partner.org']
213
214
# Use in schemas
215
file_schema = Schema(is_file) # Validates file exists
216
number_schema = Schema(is_even) # Validates even numbers
217
email_schema = Schema(is_valid_email_domain) # Validates email domain
218
219
# Combined validation
220
config_schema = Schema({
221
'log_file': is_file, # Must be existing file
222
'port': is_even, # Must be even number
223
'admin_email': is_valid_email_domain, # Must be company email
224
})
225
```
226
227
### Type Checking Patterns
228
229
Common patterns for type validation and conversion.
230
231
**Flexible Type Acceptance:**
232
233
```python
234
from voluptuous import Schema, Any, Coerce, All
235
236
# Accept multiple representations of the same data
237
flexible_id = Any(
238
int, # Already an integer
239
All(str, Coerce(int)), # String representation of integer
240
All(str, Match(r'^\d+$'), Coerce(int)), # Ensure string is numeric first
241
)
242
243
# Flexible timestamp handling
244
timestamp_validator = Any(
245
int, # Unix timestamp
246
float, # Fractional timestamp
247
All(str, Coerce(float)), # String timestamp
248
datetime.datetime, # Datetime object
249
)
250
```
251
252
**Safe Type Coercion:**
253
254
```python
255
from voluptuous import Schema, Coerce, All, message
256
257
@message("Invalid number format")
258
def safe_int(value):
259
"""Safely convert to int with better error messages."""
260
if isinstance(value, int):
261
return value
262
if isinstance(value, str) and value.strip():
263
try:
264
return int(value.strip())
265
except ValueError:
266
# Try float first, then int
267
try:
268
float_val = float(value.strip())
269
if float_val.is_integer():
270
return int(float_val)
271
except ValueError:
272
pass
273
raise ValueError("Cannot convert to integer")
274
275
# Safer than plain Coerce(int)
276
safe_number_schema = Schema(safe_int)
277
```
278
279
**Conditional Type Conversion:**
280
281
```python
282
from voluptuous import Schema, Any, All, Coerce
283
284
def smart_coerce(target_type):
285
"""Intelligently coerce values based on their current type."""
286
def coercer(value):
287
if isinstance(value, target_type):
288
return value
289
290
if target_type == bool:
291
return Boolean(value)
292
elif target_type in (int, float):
293
if isinstance(value, str) and not value.strip():
294
raise ValueError("Empty string cannot be converted to number")
295
return target_type(value)
296
else:
297
return target_type(value)
298
299
return coercer
300
301
# Smart coercion with fallbacks
302
smart_schema = Schema({
303
'count': smart_coerce(int),
304
'rate': smart_coerce(float),
305
'enabled': smart_coerce(bool),
306
})
307
```
308
309
**Type Validation with Constraints:**
310
311
```python
312
from voluptuous import Schema, All, Coerce, Range, Length
313
314
# Ensure type and constraints in one step
315
constrained_string = All(
316
str, # Must be string
317
Length(min=1, max=100), # Must have reasonable length
318
lambda s: s.strip() == s, # Must not have leading/trailing whitespace
319
)
320
321
constrained_number = All(
322
Any(int, float, Coerce(float)), # Accept various numeric types
323
Range(min=0), # Must be non-negative
324
lambda x: x == x, # Must not be NaN (NaN != NaN)
325
)
326
327
# Use in schema
328
validated_schema = Schema({
329
'name': constrained_string,
330
'amount': constrained_number,
331
})
332
```