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

core-schema.mddocs/

0

# Core Schema Framework

1

2

The foundational validation system that defines data structure rules, manages field requirements, handles extra key policies, and enables complex validation composition through markers and schema extension.

3

4

## Capabilities

5

6

### Schema Class

7

8

The main validation class that defines and executes validation rules against data structures.

9

10

```python { .api }

11

class Schema:

12

def __init__(self, schema, required=False, extra=PREVENT_EXTRA):

13

"""

14

Create a validation schema.

15

16

Parameters:

17

- schema: The validation rules (dict, list, callable, or value)

18

- required: Whether all keys are required by default (bool)

19

- extra: How to handle extra keys (PREVENT_EXTRA/ALLOW_EXTRA/REMOVE_EXTRA)

20

"""

21

22

def __call__(self, data):

23

"""

24

Validate data against the schema.

25

26

Parameters:

27

- data: Data to validate

28

29

Returns:

30

Validated and potentially transformed data

31

32

Raises:

33

Invalid: If validation fails

34

MultipleInvalid: If multiple validation errors occur

35

"""

36

37

def extend(self, schema, required=None, extra=None):

38

"""

39

Merge with another schema to create a new schema.

40

41

Parameters:

42

- schema: Schema to merge with

43

- required: Override required setting

44

- extra: Override extra key handling

45

46

Returns:

47

New Schema object with merged rules

48

"""

49

50

@classmethod

51

def infer(cls, data, **kwargs):

52

"""

53

Create a schema by inferring types from concrete data.

54

55

Parameters:

56

- data: Sample data to infer schema from

57

- kwargs: Additional options for schema creation

58

59

Returns:

60

New Schema object inferred from data types

61

"""

62

```

63

64

### Required Fields

65

66

Mark schema keys as required with optional default values.

67

68

```python { .api }

69

class Required:

70

def __init__(self, schema, msg=None, default=UNDEFINED, description=None):

71

"""

72

Mark a schema key as required.

73

74

Parameters:

75

- schema: The key to mark as required

76

- msg: Custom error message

77

- default: Default value or factory function

78

- description: Human-readable description

79

"""

80

```

81

82

**Usage Example:**

83

84

```python

85

from voluptuous import Schema, Required, DefaultTo

86

87

schema = Schema({

88

Required('name'): str,

89

Required('age', default=0): int,

90

Required('config', default=dict): dict,

91

})

92

93

# Validates successfully with defaults applied

94

result = schema({'name': 'John'})

95

# Result: {'name': 'John', 'age': 0, 'config': {}}

96

```

97

98

### Optional Fields

99

100

Mark schema keys as optional with optional default values.

101

102

```python { .api }

103

class Optional:

104

def __init__(self, schema, msg=None, default=UNDEFINED, description=None):

105

"""

106

Mark a schema key as optional.

107

108

Parameters:

109

- schema: The key to mark as optional

110

- msg: Custom error message

111

- default: Default value or factory function

112

- description: Human-readable description

113

"""

114

```

115

116

**Usage Example:**

117

118

```python

119

from voluptuous import Schema, Required, Optional

120

121

schema = Schema({

122

Required('name'): str,

123

Optional('nickname'): str,

124

Optional('tags', default=list): [str],

125

})

126

127

# Both work:

128

schema({'name': 'John'}) # nickname omitted

129

schema({'name': 'John', 'nickname': 'Johnny'}) # nickname provided

130

```

131

132

### Exclusive Fields

133

134

Create mutually exclusive field groups where only one field from the group can be present.

135

136

```python { .api }

137

class Exclusive:

138

def __init__(self, schema, group_of_exclusion, msg=None, description=None):

139

"""

140

Mark fields as mutually exclusive.

141

142

Parameters:

143

- schema: The key to mark as exclusive

144

- group_of_exclusion: Group identifier (string)

145

- msg: Custom error message

146

- description: Human-readable description

147

"""

148

```

149

150

**Usage Example:**

151

152

```python

153

from voluptuous import Schema, Exclusive

154

155

# Only one authentication method allowed

156

auth_schema = Schema({

157

Exclusive('username', 'auth'): str,

158

Exclusive('token', 'auth'): str,

159

Exclusive('api_key', 'auth'): str,

160

})

161

162

# Valid: only one auth method

163

auth_schema({'username': 'john'})

164

auth_schema({'token': 'abc123'})

165

166

# Invalid: multiple auth methods

167

# auth_schema({'username': 'john', 'token': 'abc123'}) # Raises ExclusiveInvalid

168

```

169

170

### Inclusive Fields

171

172

Create inclusive field groups where if any field from the group is present, all must be present.

173

174

```python { .api }

175

class Inclusive:

176

def __init__(self, schema, group_of_inclusion, msg=None, description=None, default=UNDEFINED):

177

"""

178

Mark fields as inclusive (all-or-nothing).

179

180

Parameters:

181

- schema: The key to mark as inclusive

182

- group_of_inclusion: Group identifier (string)

183

- msg: Custom error message

184

- description: Human-readable description

185

- default: Default value if group is missing

186

"""

187

```

188

189

**Usage Example:**

190

191

```python

192

from voluptuous import Schema, Inclusive, Required

193

194

# Coordinates must be provided together

195

location_schema = Schema({

196

Required('name'): str,

197

Inclusive('latitude', 'coords'): float,

198

Inclusive('longitude', 'coords'): float,

199

})

200

201

# Valid: both coords or neither

202

location_schema({'name': 'Home'}) # No coordinates

203

location_schema({'name': 'Home', 'latitude': 40.7, 'longitude': -74.0}) # Both coordinates

204

205

# Invalid: only one coordinate

206

# location_schema({'name': 'Home', 'latitude': 40.7}) # Raises InclusiveInvalid

207

```

208

209

### Remove Fields

210

211

Mark fields for removal from validated output, treating validation failures as extra keys.

212

213

```python { .api }

214

class Remove:

215

def __init__(self, schema, msg=None, description=None):

216

"""

217

Mark a field for removal from output.

218

219

Parameters:

220

- schema: The key to remove from output

221

- msg: Custom error message (rarely used)

222

- description: Human-readable description

223

"""

224

```

225

226

**Usage Example:**

227

228

```python

229

from voluptuous import Schema, Remove, Required

230

231

# Remove sensitive fields from output

232

schema = Schema({

233

Required('name'): str,

234

Required('email'): str,

235

Remove('password'): str, # Validated but not included in result

236

})

237

238

data = {'name': 'John', 'email': 'john@example.com', 'password': 'secret'}

239

result = schema(data)

240

# Result: {'name': 'John', 'email': 'john@example.com'}

241

# Password was validated but removed from output

242

```

243

244

### Object Validation

245

246

Validate object attributes instead of dictionary keys, useful for class instances.

247

248

```python { .api }

249

class Object(dict):

250

def __init__(self, schema, cls=UNDEFINED):

251

"""

252

Validate object attributes instead of dict keys.

253

254

Parameters:

255

- schema: Validation schema for object attributes

256

- cls: Expected class type (optional)

257

"""

258

```

259

260

**Usage Example:**

261

262

```python

263

from voluptuous import Schema, Object, Required

264

265

class User:

266

def __init__(self, name, age):

267

self.name = name

268

self.age = age

269

270

user_schema = Schema(Object({

271

Required('name'): str,

272

Required('age'): int,

273

}))

274

275

user = User('John', 30)

276

validated_user = user_schema(user) # Validates object attributes

277

```

278

279

### Custom Error Messages

280

281

Provide custom error messages and exception types for validation failures.

282

283

```python { .api }

284

class Msg:

285

def __init__(self, schema, msg, cls=None):

286

"""

287

Provide custom error message for validation.

288

289

Parameters:

290

- schema: The schema to validate

291

- msg: Custom error message

292

- cls: Custom exception class to raise (defaults to ValueError)

293

"""

294

```

295

296

**Usage Example:**

297

298

```python

299

from voluptuous import Schema, Msg, All, Length

300

301

password_schema = Schema(

302

Msg(All(str, Length(min=8)), 'Password must be at least 8 characters', ValueError)

303

)

304

305

try:

306

password_schema('short')

307

except ValueError as e:

308

print(e) # "Password must be at least 8 characters"

309

```

310

311

### Extra Key Handling

312

313

Control how schema validation handles keys not defined in the schema.

314

315

```python { .api }

316

PREVENT_EXTRA = 0 # Raise error for extra keys (default)

317

ALLOW_EXTRA = 1 # Include extra keys in output

318

REMOVE_EXTRA = 2 # Exclude extra keys from output

319

320

def Extra(_):

321

"""Placeholder function for allowing extra keys in schema definition."""

322

```

323

324

**Usage Example:**

325

326

```python

327

from voluptuous import Schema, Required, ALLOW_EXTRA, REMOVE_EXTRA

328

329

# Allow extra keys

330

flexible_schema = Schema({

331

Required('name'): str,

332

}, extra=ALLOW_EXTRA)

333

334

# Remove extra keys

335

strict_schema = Schema({

336

Required('name'): str,

337

}, extra=REMOVE_EXTRA)

338

339

data = {'name': 'John', 'extra_field': 'value'}

340

341

flexible_result = flexible_schema(data) # {'name': 'John', 'extra_field': 'value'}

342

strict_result = strict_schema(data) # {'name': 'John'}

343

```

344

345

### Utility Functions

346

347

Helper functions for schema creation and validation.

348

349

```python { .api }

350

def message(msg=None, cls=None):

351

"""

352

Decorator to add custom error messages to validator functions.

353

354

Parameters:

355

- msg: Custom error message

356

- cls: Custom exception class

357

"""

358

359

def validate(*a, **kw):

360

"""

361

Decorator for validating function arguments against a schema.

362

363

Parameters:

364

- *a: Positional argument schemas

365

- **kw: Keyword argument schemas

366

"""

367

368

def default_factory(value):

369

"""

370

Convert a value to a factory function for default values.

371

372

Parameters:

373

- value: Value to convert (if callable, returns as-is; otherwise wraps in lambda)

374

375

Returns:

376

Factory function that returns the value

377

"""

378

379

def raises(exc, msg=None, regex=None):

380

"""

381

Context manager for testing that an exception is raised.

382

383

Parameters:

384

- exc: Exception class that should be raised

385

- msg: Optional exact error message to match

386

- regex: Optional regex pattern to match against error message

387

388

Returns:

389

Context manager for use with 'with' statement

390

391

Raises:

392

AssertionError: If expected exception is not raised or message doesn't match

393

"""

394

```

395

396

**Message Decorator Example:**

397

398

```python

399

from voluptuous import message, Schema

400

401

@message("Value must be positive", ValueError)

402

def positive(value):

403

if value <= 0:

404

raise ValueError()

405

return value

406

407

schema = Schema(positive)

408

```

409

410

**Validate Decorator Example:**

411

412

```python

413

from voluptuous import validate, Schema, Required

414

415

@validate({'name': str, 'age': int})

416

def create_user(data):

417

return f"User: {data['name']}, Age: {data['age']}"

418

419

# Function arguments are automatically validated

420

create_user({'name': 'John', 'age': 30})

421

```

422

423

**Testing Utility Example:**

424

425

```python

426

from voluptuous import raises, Schema, Invalid, Range

427

428

# Test that validation raises expected exceptions

429

with raises(Invalid):

430

Schema(Range(min=0, max=10))(15) # Should raise Invalid

431

432

# Test with specific error message

433

with raises(Invalid, "value must be at most 10"):

434

Schema(Range(min=0, max=10))(15)

435

436

# Test with regex pattern

437

import re

438

with raises(Invalid, regex=re.compile(r"value must be at most \d+")):

439

Schema(Range(min=0, max=10))(15)

440

```