or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

core-schema.mderror-handling.mdindex.mdrange-collection-validators.mdstring-pattern-validators.mdtype-validators.mdutility-transformers.mdvalidation-composers.md

utility-transformers.mddocs/

0

# Utility Transformers

1

2

String transformation utilities, default value handling, value setting, and collection conversion utilities. These transformers modify data during validation rather than just validating it.

3

4

## Capabilities

5

6

### String Transformation

7

8

Functions that transform strings while validating them.

9

10

```python { .api }

11

def Lower(v):

12

"""

13

Transform string to lowercase.

14

15

Parameters:

16

- v: String to transform

17

18

Returns:

19

Lowercase version of input string

20

21

Raises:

22

Invalid: If input cannot be converted to string

23

"""

24

25

def Upper(v):

26

"""

27

Transform string to uppercase.

28

29

Parameters:

30

- v: String to transform

31

32

Returns:

33

Uppercase version of input string

34

35

Raises:

36

Invalid: If input cannot be converted to string

37

"""

38

39

def Capitalize(v):

40

"""

41

Capitalize first letter of string.

42

43

Parameters:

44

- v: String to transform

45

46

Returns:

47

String with first letter capitalized, rest lowercase

48

49

Raises:

50

Invalid: If input cannot be converted to string

51

"""

52

53

def Title(v):

54

"""

55

Transform string to title case (each word capitalized).

56

57

Parameters:

58

- v: String to transform

59

60

Returns:

61

String in title case

62

63

Raises:

64

Invalid: If input cannot be converted to string

65

"""

66

67

def Strip(v):

68

"""

69

Remove leading and trailing whitespace from string.

70

71

Parameters:

72

- v: String to transform

73

74

Returns:

75

String with whitespace stripped

76

77

Raises:

78

Invalid: If input cannot be converted to string

79

"""

80

```

81

82

**Usage Examples:**

83

84

```python

85

from voluptuous import Schema, All, Lower, Upper, Capitalize, Title, Strip, Length

86

87

# Data normalization

88

user_schema = Schema({

89

'username': All(str, Strip, Lower), # Clean and lowercase username

90

'name': All(str, Strip, Title), # Clean and title case name

91

'email': All(str, Strip, Lower), # Clean and lowercase email

92

'country': All(str, Strip, Upper), # Clean and uppercase country code

93

})

94

95

# Text processing pipeline

96

text_processor = All(

97

str, # Ensure string

98

Strip, # Remove whitespace

99

lambda s: s if s else None, # Convert empty strings to None

100

)

101

102

# Combined with validation

103

clean_name = All(

104

str,

105

Strip, # Remove whitespace

106

Title, # Title case

107

Length(min=1, max=100), # Validate length

108

)

109

110

# Usage examples:

111

user_schema({

112

'username': ' JohnDoe ', # -> 'johndoe'

113

'name': ' john doe ', # -> 'John Doe'

114

'email': ' JOHN@EXAMPLE.COM ', # -> 'john@example.com'

115

'country': ' usa ', # -> 'USA'

116

})

117

```

118

119

### Default Value Handling

120

121

Set default values when input is None or missing.

122

123

```python { .api }

124

class DefaultTo:

125

def __init__(self, default_value, msg=None):

126

"""

127

Set default value when input is None.

128

129

Parameters:

130

- default_value: Value to use when input is None (can be callable for factory)

131

- msg: Custom error message (rarely used)

132

133

Returns:

134

Input value if not None, otherwise default_value (or result of calling it)

135

136

Note:

137

If default_value is callable, it will be called each time to generate the default

138

"""

139

```

140

141

**Usage Examples:**

142

143

```python

144

from voluptuous import Schema, DefaultTo, Required, Optional

145

146

# Simple default values

147

config_schema = Schema({

148

Required('host', default='localhost'): str, # Default host

149

Required('port', default=8080): int, # Default port

150

Required('debug', default=False): bool, # Default debug mode

151

})

152

153

# Factory functions for dynamic defaults

154

import datetime

155

156

session_schema = Schema({

157

'user_id': str,

158

'created_at': DefaultTo(datetime.datetime.now), # Current time as default

159

'expires_at': DefaultTo(lambda: datetime.datetime.now() + datetime.timedelta(hours=24)),

160

'permissions': DefaultTo(list), # Empty list as default

161

'metadata': DefaultTo(dict), # Empty dict as default

162

})

163

164

# Conditional defaults

165

def default_config():

166

return {'theme': 'light', 'language': 'en'}

167

168

user_prefs_schema = Schema({

169

'username': str,

170

'config': DefaultTo(default_config), # Function returns dict

171

})

172

173

# Usage examples:

174

config_schema({'host': None}) # -> {'host': 'localhost', 'port': 8080, 'debug': False}

175

session_schema({'user_id': '123'}) # Adds timestamps and empty collections

176

```

177

178

### Value Setting

179

180

Always set specific values regardless of input.

181

182

```python { .api }

183

class SetTo:

184

def __init__(self, value):

185

"""

186

Always set to specific value, ignoring input.

187

188

Parameters:

189

- value: Value to always return (can be callable for factory)

190

191

Returns:

192

The specified value (or result of calling it if callable)

193

194

Note:

195

Completely ignores the input value

196

"""

197

```

198

199

**Usage Examples:**

200

201

```python

202

from voluptuous import Schema, SetTo, Any, All

203

import uuid

204

import datetime

205

206

# Always set specific values

207

audit_schema = Schema({

208

'data': dict, # User data

209

'created_by': SetTo('system'), # Always 'system'

210

'created_at': SetTo(datetime.datetime.now), # Always current time

211

'id': SetTo(lambda: str(uuid.uuid4())), # Always new UUID

212

'version': SetTo(1), # Always version 1

213

})

214

215

# Conditional value setting

216

def status_based_priority(data):

217

if data.get('status') == 'urgent':

218

return SetTo(1) # High priority

219

elif data.get('status') == 'low':

220

return SetTo(5) # Low priority

221

else:

222

return SetTo(3) # Medium priority

223

224

task_schema = Schema({

225

'title': str,

226

'status': str,

227

'priority': status_based_priority, # Set based on status

228

})

229

230

# Default or override pattern

231

flexible_schema = Schema({

232

'name': str,

233

'type': Any(str, SetTo('default')), # Use provided or default to 'default'

234

})

235

236

# Usage examples:

237

audit_result = audit_schema({'data': {'key': 'value'}})

238

# Result includes system-generated fields regardless of input

239

240

task_result = task_schema({'title': 'Fix bug', 'status': 'urgent'})

241

# Result: {'title': 'Fix bug', 'status': 'urgent', 'priority': 1}

242

```

243

244

### Collection Conversion

245

246

Convert between different collection types.

247

248

```python { .api }

249

class Set:

250

def __init__(self, msg=None):

251

"""

252

Convert iterable to Python set.

253

254

Parameters:

255

- msg: Custom error message if conversion fails

256

257

Returns:

258

Set containing unique elements from input iterable

259

260

Raises:

261

TypeInvalid: If input cannot be converted to set (not iterable or contains unhashable types)

262

"""

263

```

264

265

**Usage Examples:**

266

267

```python

268

from voluptuous import Schema, Set, All, Length

269

270

# Remove duplicates by converting to set

271

unique_tags_schema = Schema({

272

'tags': All([str], Set()), # Convert list to set (removes duplicates)

273

})

274

275

# Validate set properties

276

permissions_schema = Schema(All(

277

[str], # Start with list of strings

278

Set(), # Convert to set

279

lambda s: len(s) >= 2, # Must have at least 2 unique permissions

280

))

281

282

# Combined with other validation

283

category_schema = Schema(All(

284

[str], # List of strings

285

lambda lst: [s.strip().lower() for s in lst], # Normalize

286

Set(), # Remove duplicates

287

lambda s: len(s) <= 10, # Max 10 unique categories

288

))

289

290

# Usage examples:

291

unique_tags_schema({'tags': ['python', 'web', 'python', 'api']})

292

# Result: {'tags': {'python', 'web', 'api'}}

293

294

permissions_schema(['read', 'write', 'read', 'admin'])

295

# Result: {'read', 'write', 'admin'}

296

```

297

298

### Literal Value Matching

299

300

Validate exact literal values with custom comparison.

301

302

```python { .api }

303

class Literal:

304

def __init__(self, lit):

305

"""

306

Validate exact literal value match.

307

308

Parameters:

309

- lit: Literal value that input must exactly match

310

311

Returns:

312

The literal value if input matches exactly

313

314

Raises:

315

LiteralInvalid: If input doesn't match literal value exactly

316

"""

317

```

318

319

**Usage Examples:**

320

321

```python

322

from voluptuous import Schema, Literal, Any

323

324

# API version validation

325

api_schema = Schema({

326

'version': Literal('v1'), # Must be exactly 'v1'

327

'format': Literal('json'), # Must be exactly 'json'

328

})

329

330

# Multiple literal options

331

status_schema = Schema({

332

'status': Any(

333

Literal('active'),

334

Literal('inactive'),

335

Literal('pending'),

336

),

337

})

338

339

# Configuration flags

340

feature_flags = Schema({

341

'new_ui': Any(Literal(True), Literal(False)), # Boolean literals

342

'api_version': Any(Literal(1), Literal(2)), # Integer literals

343

'mode': Any(Literal('dev'), Literal('prod')), # String literals

344

})

345

346

# Null/None validation

347

nullable_field = Schema({

348

'optional_field': Any(str, Literal(None)), # String or exactly None

349

})

350

351

# Usage examples:

352

api_schema({'version': 'v1', 'format': 'json'}) # Valid

353

# api_schema({'version': 'v2', 'format': 'json'}) # Invalid - wrong version

354

355

status_schema({'status': 'active'}) # Valid

356

feature_flags({'new_ui': True, 'api_version': 1, 'mode': 'prod'}) # Valid

357

```

358

359

### Transformation Pipelines

360

361

Complex data transformation patterns using multiple transformers.

362

363

**Text Normalization Pipeline:**

364

365

```python

366

from voluptuous import Schema, All, Strip, Lower, Replace, Length

367

import re

368

369

# Complete text normalization

370

normalize_text = All(

371

str, # Ensure string

372

Strip, # Remove leading/trailing whitespace

373

lambda s: re.sub(r'\s+', ' ', s), # Normalize internal whitespace

374

Lower, # Convert to lowercase

375

lambda s: s if s else None, # Convert empty strings to None

376

)

377

378

# URL slug generation

379

create_slug = All(

380

str,

381

Strip,

382

Lower,

383

Replace(r'[^\w\s-]', ''), # Remove special characters

384

Replace(r'\s+', '-'), # Replace spaces with hyphens

385

Replace(r'-+', '-'), # Collapse multiple hyphens

386

lambda s: s.strip('-'), # Remove leading/trailing hyphens

387

)

388

389

# Usage:

390

normalize_text(' Hello World ') # -> 'hello world'

391

create_slug('My Blog Post Title!') # -> 'my-blog-post-title'

392

```

393

394

**Data Cleaning Pipeline:**

395

396

```python

397

from voluptuous import Schema, All, DefaultTo, Strip, Coerce

398

399

# Clean and validate user input

400

clean_user_data = Schema({

401

'name': All(str, Strip, DefaultTo('Anonymous')),

402

'age': All(Any(int, str), Coerce(int), Range(min=0, max=150)),

403

'email': All(str, Strip, Lower, Any(Email(), DefaultTo(None))),

404

'tags': All(

405

Any(list, str), # Accept list or comma-separated string

406

lambda x: x.split(',') if isinstance(x, str) else x, # Split if string

407

[All(str, Strip)], # Clean each tag

408

lambda tags: [t for t in tags if t], # Remove empty tags

409

Set(), # Remove duplicates

410

),

411

})

412

```

413

414

**Configuration Processing:**

415

416

```python

417

from voluptuous import Schema, All, DefaultTo, Coerce, Any

418

419

# Process configuration with defaults and coercion

420

config_processor = Schema({

421

'database': {

422

'host': All(str, Strip, DefaultTo('localhost')),

423

'port': All(Any(int, str), Coerce(int), Range(min=1024, max=65535), DefaultTo(5432)),

424

'name': All(str, Strip),

425

'ssl': All(Any(bool, str), Boolean, DefaultTo(True)),

426

},

427

'cache': {

428

'enabled': All(Any(bool, str), Boolean, DefaultTo(False)),

429

'ttl': All(Any(int, str), Coerce(int), Range(min=1), DefaultTo(3600)),

430

},

431

'features': All(

432

Any([str], str), # List or comma-separated string

433

lambda x: x.split(',') if isinstance(x, str) else x,

434

[All(str, Strip, Lower)], # Normalize feature names

435

Set(), # Remove duplicates

436

DefaultTo(set()), # Default to empty set

437

),

438

})

439

```

440

441

**Flexible Data Transformation:**

442

443

```python

444

from voluptuous import Schema, All, Any, SetTo

445

446

def smart_transform(field_name, transforms):

447

"""Apply different transformations based on field name or value."""

448

def transformer(value):

449

for condition, transform in transforms:

450

if condition(field_name, value):

451

return transform(value)

452

return value

453

return transformer

454

455

# Dynamic field processing

456

dynamic_schema = Schema({

457

'username': smart_transform('username', [

458

(lambda f, v: isinstance(v, str), All(Strip, Lower)),

459

(lambda f, v: True, SetTo('anonymous')), # Fallback

460

]),

461

'created_at': smart_transform('created_at', [

462

(lambda f, v: v is None, SetTo(datetime.datetime.now)),

463

(lambda f, v: isinstance(v, str), lambda s: datetime.datetime.fromisoformat(s)),

464

(lambda f, v: True, lambda x: x), # Pass through

465

]),

466

})

467

```