or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli.mdcore-functions.mdexceptions.mdindex.mdschema-management.mdvalidators.md

exceptions.mddocs/

0

# Exception Handling

1

2

Error handling and testing utilities for comprehensive validation workflows and error reporting. Yamale provides specialized exception classes and testing utilities for robust error handling in validation scenarios.

3

4

## Capabilities

5

6

### YamaleError Exception

7

8

Main exception class raised when YAML validation fails, containing detailed error information for all failed validations.

9

10

```python { .api }

11

class YamaleError(ValueError):

12

"""

13

Exception raised when YAML validation fails.

14

Inherits from ValueError for standard exception handling.

15

"""

16

17

def __init__(self, results):

18

"""

19

Initialize YamaleError with validation results.

20

21

Parameters:

22

- results (list): List of ValidationResult objects containing errors

23

24

Attributes:

25

- message (str): Combined error message from all failed validations

26

- results (list): List of ValidationResult objects

27

"""

28

29

message: str # Formatted error message string

30

results: list # List of ValidationResult objects with detailed errors

31

```

32

33

Usage examples:

34

35

```python

36

import yamale

37

38

try:

39

yamale.validate(schema, data)

40

print("Validation successful!")

41

except yamale.YamaleError as e:

42

# Access the combined error message

43

print(f"Validation failed: {e}")

44

print(f"Error message: {e.message}")

45

46

# Process individual validation results

47

print(f"Failed validations: {len([r for r in e.results if not r.isValid()])}")

48

for result in e.results:

49

if not result.isValid():

50

print(f"\nFile: {result.data}")

51

print(f"Schema: {result.schema}")

52

for error in result.errors:

53

print(f" - {error}")

54

55

# Handle as standard ValueError

56

except ValueError as e:

57

print(f"General validation error: {e}")

58

```

59

60

### Detailed Error Information

61

62

YamaleError provides structured access to validation failures:

63

64

```python

65

try:

66

yamale.validate(schema, data)

67

except yamale.YamaleError as e:

68

# Get summary statistics

69

total_results = len(e.results)

70

failed_results = [r for r in e.results if not r.isValid()]

71

success_rate = (total_results - len(failed_results)) / total_results * 100

72

73

print(f"Validation Summary:")

74

print(f" Total files: {total_results}")

75

print(f" Failed: {len(failed_results)}")

76

print(f" Success rate: {success_rate:.1f}%")

77

78

# Group errors by type

79

error_types = {}

80

for result in failed_results:

81

for error in result.errors:

82

error_type = error.split(':')[0] if ':' in error else 'General'

83

error_types[error_type] = error_types.get(error_type, 0) + 1

84

85

print(f"\nError breakdown:")

86

for error_type, count in error_types.items():

87

print(f" {error_type}: {count}")

88

```

89

90

### YamaleTestCase Class

91

92

Unittest.TestCase subclass for easy integration of YAML validation into unit testing frameworks.

93

94

```python { .api }

95

class YamaleTestCase(TestCase):

96

"""

97

TestCase subclass for validating YAML files in unit tests.

98

Inherits from unittest.TestCase.

99

"""

100

101

schema = None # String path to schema file (required)

102

yaml = None # String path or list of paths to YAML files (required)

103

base_dir = None # String path to prepend to all other paths (optional)

104

105

def validate(self, validators=None):

106

"""

107

Validate configured YAML files against schema.

108

109

Parameters:

110

- validators (dict, optional): Custom validator dictionary

111

112

Returns:

113

bool: True if all validations pass

114

115

Raises:

116

ValueError: If validation fails or configuration is invalid

117

"""

118

```

119

120

Usage examples:

121

122

```python

123

import os

124

import yamale

125

from yamale import YamaleTestCase

126

127

class TestUserConfigs(YamaleTestCase):

128

# Required configuration

129

schema = 'schemas/user.yaml'

130

yaml = 'data/users/*.yaml' # Supports glob patterns

131

base_dir = os.path.dirname(os.path.realpath(__file__))

132

133

def runTest(self):

134

# Validate all matching files

135

self.assertTrue(self.validate())

136

137

class TestMultipleFiles(YamaleTestCase):

138

schema = 'config-schema.yaml'

139

yaml = ['config.yaml', 'config-prod.yaml', 'config-dev.yaml']

140

141

def runTest(self):

142

self.assertTrue(self.validate())

143

144

class TestWithCustomValidators(YamaleTestCase):

145

schema = 'custom-schema.yaml'

146

yaml = 'custom-data.yaml'

147

148

def runTest(self):

149

# Use custom validators

150

custom_validators = yamale.validators.DefaultValidators.copy()

151

custom_validators['email'] = EmailValidator

152

self.assertTrue(self.validate(validators=custom_validators))

153

154

# Run tests

155

if __name__ == '__main__':

156

import unittest

157

unittest.main()

158

```

159

160

### Advanced Testing Patterns

161

162

#### Test Suite Organization

163

164

```python

165

import unittest

166

import os

167

from yamale import YamaleTestCase

168

169

class BaseYamaleTest(YamaleTestCase):

170

"""Base class with common configuration."""

171

base_dir = os.path.join(os.path.dirname(__file__), 'fixtures')

172

173

class TestAPISchemas(BaseYamaleTest):

174

schema = 'api-schema.yaml'

175

yaml = 'api-examples/*.yaml'

176

177

def runTest(self):

178

self.assertTrue(self.validate())

179

180

class TestConfigSchemas(BaseYamaleTest):

181

schema = 'config-schema.yaml'

182

yaml = ['config-*.yaml']

183

184

def runTest(self):

185

self.assertTrue(self.validate())

186

187

# Create test suite

188

def create_yamale_suite():

189

suite = unittest.TestSuite()

190

suite.addTest(TestAPISchemas())

191

suite.addTest(TestConfigSchemas())

192

return suite

193

```

194

195

#### Error Handling in Tests

196

197

```python

198

class TestWithErrorHandling(YamaleTestCase):

199

schema = 'strict-schema.yaml'

200

yaml = 'test-data.yaml'

201

202

def runTest(self):

203

try:

204

result = self.validate()

205

self.assertTrue(result)

206

except ValueError as e:

207

# Log detailed error information for debugging

208

self.fail(f"Validation failed: {e}")

209

210

def test_expected_failure(self):

211

"""Test that intentionally invalid data fails validation."""

212

# Temporarily change to invalid data

213

original_yaml = self.yaml

214

self.yaml = 'invalid-data.yaml'

215

216

with self.assertRaises(ValueError):

217

self.validate()

218

219

# Restore original configuration

220

self.yaml = original_yaml

221

```

222

223

### Integration with Testing Frameworks

224

225

#### pytest Integration

226

227

```python

228

import pytest

229

import yamale

230

231

def test_yaml_validation():

232

"""Test YAML validation using pytest."""

233

schema = yamale.make_schema('./schema.yaml')

234

data = yamale.make_data('./data.yaml')

235

236

try:

237

yamale.validate(schema, data)

238

except yamale.YamaleError as e:

239

pytest.fail(f"YAML validation failed: {e}")

240

241

@pytest.mark.parametrize("data_file", [

242

"config-dev.yaml",

243

"config-prod.yaml",

244

"config-test.yaml"

245

])

246

def test_multiple_configs(data_file):

247

"""Test multiple configuration files."""

248

schema = yamale.make_schema('./config-schema.yaml')

249

data = yamale.make_data(f'./configs/{data_file}')

250

251

yamale.validate(schema, data) # Will raise on failure

252

253

def test_validation_with_custom_message():

254

"""Test with custom error handling."""

255

schema = yamale.make_schema('./user-schema.yaml')

256

data = yamale.make_data('./invalid-user.yaml')

257

258

with pytest.raises(yamale.YamaleError) as exc_info:

259

yamale.validate(schema, data)

260

261

# Assert specific error conditions

262

error_msg = str(exc_info.value)

263

assert "age" in error_msg

264

assert "required" in error_msg

265

```

266

267

## Error Handling Best Practices

268

269

### Production Error Handling

270

271

```python

272

import logging

273

import yamale

274

275

def validate_config_file(config_path, schema_path):

276

"""

277

Validate configuration file with comprehensive error handling.

278

"""

279

logger = logging.getLogger(__name__)

280

281

try:

282

# Create schema

283

schema = yamale.make_schema(schema_path)

284

logger.info(f"Loaded schema from {schema_path}")

285

286

# Load data

287

data = yamale.make_data(config_path)

288

logger.info(f"Loaded data from {config_path}")

289

290

# Validate

291

yamale.validate(schema, data)

292

logger.info("Validation successful")

293

return True

294

295

except FileNotFoundError as e:

296

logger.error(f"File not found: {e}")

297

return False

298

except yaml.YAMLError as e:

299

logger.error(f"YAML parsing error: {e}")

300

return False

301

except yamale.YamaleError as e:

302

logger.error(f"Validation failed: {e}")

303

# Log detailed errors for debugging

304

for result in e.results:

305

if not result.isValid():

306

logger.debug(f"Failed file: {result.data}")

307

for error in result.errors:

308

logger.debug(f" Error: {error}")

309

return False

310

except Exception as e:

311

logger.error(f"Unexpected error: {e}")

312

return False

313

314

# Usage

315

if validate_config_file('config.yaml', 'schema.yaml'):

316

print("Configuration is valid")

317

else:

318

print("Configuration validation failed")

319

sys.exit(1)

320

```

321

322

### Batch Validation with Error Aggregation

323

324

```python

325

def validate_multiple_files(file_paths, schema_path):

326

"""

327

Validate multiple files and aggregate errors.

328

"""

329

schema = yamale.make_schema(schema_path)

330

all_results = []

331

332

for file_path in file_paths:

333

try:

334

data = yamale.make_data(file_path)

335

results = yamale.validate(schema, data, _raise_error=False)

336

all_results.extend(results)

337

except Exception as e:

338

# Create error result for files that couldn't be loaded

339

error_result = yamale.schema.validationresults.Result([str(e)])

340

error_result.data = file_path

341

error_result.schema = schema_path

342

all_results.append(error_result)

343

344

# Analyze results

345

valid_count = sum(1 for r in all_results if r.isValid())

346

total_count = len(all_results)

347

348

print(f"Validation Summary: {valid_count}/{total_count} files valid")

349

350

# Report failures

351

for result in all_results:

352

if not result.isValid():

353

print(f"FAILED: {result.data}")

354

for error in result.errors:

355

print(f" {error}")

356

357

return valid_count == total_count

358

```