0
# Utility Functions and Error Handling
1
2
Helper functions, utilities, and exception classes that support the core functionality of datamodel-code-generator. These provide YAML processing, version information, directory management, and structured error handling.
3
4
```python
5
from datamodel_code_generator import (
6
get_version,
7
load_yaml,
8
load_yaml_from_path,
9
chdir,
10
infer_input_type,
11
is_openapi,
12
is_schema,
13
get_first_file,
14
enable_debug_message,
15
snooper_to_methods
16
)
17
```
18
19
## Capabilities
20
21
### Version Information
22
23
Functions for retrieving package version and compatibility information.
24
25
```python { .api }
26
def get_version() -> str:
27
"""
28
Get the current package version string.
29
30
Returns:
31
Version string (e.g., "0.33.0")
32
33
Note:
34
Uses importlib.metadata.version() to retrieve version
35
from package metadata at runtime.
36
"""
37
```
38
39
### YAML Processing
40
41
Functions for loading and parsing YAML content with safe loading practices.
42
43
```python { .api }
44
def load_yaml(stream: str | TextIO) -> Any:
45
"""
46
Load YAML content from string or text stream.
47
48
Args:
49
stream: YAML content as string or TextIO stream
50
51
Returns:
52
Parsed YAML data structure (dict, list, scalar, etc.)
53
54
Raises:
55
yaml.parser.ParserError: If YAML content is malformed
56
57
Note:
58
Uses SafeLoader for security - prevents arbitrary code execution
59
"""
60
61
def load_yaml_from_path(path: Path, encoding: str) -> Any:
62
"""
63
Load YAML content from file path.
64
65
Args:
66
path: Path to YAML file
67
encoding: File encoding to use
68
69
Returns:
70
Parsed YAML data structure
71
72
Raises:
73
FileNotFoundError: If file does not exist
74
yaml.parser.ParserError: If YAML content is malformed
75
"""
76
```
77
78
### Directory Management
79
80
Context manager for temporary directory changes during generation.
81
82
```python { .api }
83
@contextmanager
84
def chdir(path: Path | None) -> Iterator[None]:
85
"""
86
Context manager for temporary directory changes.
87
88
Changes working directory to specified path and restores
89
original directory on exit. If path is None, no change occurs.
90
91
Args:
92
path: Target directory path, or None for no change
93
94
Yields:
95
None
96
97
Example:
98
with chdir(Path("/tmp")):
99
# Working directory is now /tmp
100
generate(input_=Path("schema.json"), output=Path("models.py"))
101
# Working directory restored to original
102
"""
103
```
104
105
### Input Format Detection
106
107
Functions for automatically detecting input schema formats.
108
109
```python { .api }
110
def infer_input_type(text: str) -> InputFileType:
111
"""
112
Automatically detect input file type from content.
113
114
Analyzes content structure to determine most likely schema format.
115
Uses heuristics like presence of 'openapi' field, '$schema' field,
116
and data structure patterns.
117
118
Args:
119
text: Raw input content as string
120
121
Returns:
122
Detected InputFileType enum value
123
124
Raises:
125
Error: If input type cannot be determined
126
127
Detection Logic:
128
1. Try parsing as YAML/JSON
129
2. Check for OpenAPI indicators ('openapi' field)
130
3. Check for JSON Schema indicators ('$schema', 'type', etc.)
131
4. Fall back to JSON for dict-like structures
132
5. Fall back to CSV if YAML parsing fails
133
"""
134
135
def is_openapi(data: dict) -> bool:
136
"""
137
Check if dictionary contains OpenAPI specification.
138
139
Args:
140
data: Parsed data dictionary
141
142
Returns:
143
True if data appears to be OpenAPI spec
144
145
Note:
146
Checks for presence of 'openapi' field in root level
147
"""
148
149
def is_schema(data: dict) -> bool:
150
"""
151
Check if dictionary contains JSON Schema.
152
153
Args:
154
data: Parsed data dictionary
155
156
Returns:
157
True if data appears to be JSON Schema
158
159
Detection Logic:
160
- Checks for $schema field with JSON Schema URL
161
- Checks for 'type' field with string value
162
- Checks for schema keywords (allOf, anyOf, oneOf)
163
- Checks for 'properties' field with dict value
164
"""
165
```
166
167
### File System Utilities
168
169
Helper functions for file and directory operations.
170
171
```python { .api }
172
def get_first_file(path: Path) -> Path:
173
"""
174
Get first file from path (file or directory).
175
176
If path is a file, returns the path itself.
177
If path is a directory, recursively finds first file.
178
179
Args:
180
path: File or directory path
181
182
Returns:
183
Path to first file found
184
185
Raises:
186
FileNotFoundError: If no files found in directory
187
"""
188
```
189
190
### Error Handling
191
192
Exception classes for structured error handling and user feedback.
193
194
```python { .api }
195
class Error(Exception):
196
"""
197
Base exception class for datamodel-code-generator.
198
199
Provides structured error handling with descriptive messages
200
for generation failures, validation errors, and processing issues.
201
"""
202
203
def __init__(self, message: str) -> None:
204
"""
205
Initialize error with descriptive message.
206
207
Args:
208
message: Human-readable error description
209
"""
210
self.message: str = message
211
212
def __str__(self) -> str:
213
"""Return error message for display."""
214
return self.message
215
216
class InvalidClassNameError(Error):
217
"""
218
Raised when generated class names are invalid Python identifiers.
219
220
Occurs when schema titles or field names cannot be converted
221
to valid Python class names due to reserved keywords,
222
special characters, or naming conflicts.
223
"""
224
225
def __init__(self, class_name: str) -> None:
226
"""
227
Initialize with invalid class name.
228
229
Args:
230
class_name: The invalid class name that caused the error
231
"""
232
self.class_name = class_name
233
message = f"title={class_name!r} is invalid class name."
234
super().__init__(message=message)
235
```
236
237
### Debug Support
238
239
Functions for enabling debug tracing and diagnostics.
240
241
```python { .api }
242
def enable_debug_message() -> None:
243
"""
244
Enable debug message tracing.
245
246
Activates pysnooper-based debug tracing for detailed
247
execution flow analysis. Requires 'debug' extra installation.
248
249
Raises:
250
Exception: If debug dependencies not installed
251
252
Note:
253
Install with: pip install 'datamodel-code-generator[debug]'
254
"""
255
256
def snooper_to_methods() -> Callable[..., Any]:
257
"""
258
Class decorator for adding debug tracing to all methods.
259
260
Returns:
261
Decorator function that adds snooper tracing to class methods
262
263
Usage:
264
@snooper_to_methods()
265
class MyParser:
266
def parse(self): ...
267
"""
268
```
269
270
## Usage Examples
271
272
### Version Information
273
```python
274
from datamodel_code_generator import get_version
275
276
print(f"Using datamodel-code-generator version: {get_version()}")
277
# Output: Using datamodel-code-generator version: 0.33.0
278
```
279
280
### YAML Processing
281
```python
282
from datamodel_code_generator import load_yaml, load_yaml_from_path
283
from pathlib import Path
284
285
# Load from string
286
yaml_content = """
287
openapi: 3.0.0
288
info:
289
title: My API
290
version: 1.0.0
291
"""
292
data = load_yaml(yaml_content)
293
print(data['info']['title']) # My API
294
295
# Load from file
296
schema_data = load_yaml_from_path(Path("schema.yaml"), encoding="utf-8")
297
```
298
299
### Directory Management
300
```python
301
from datamodel_code_generator import chdir, generate
302
from pathlib import Path
303
304
# Generate with specific working directory
305
with chdir(Path("/project/schemas")):
306
generate(
307
input_=Path("api.yaml"), # Relative to /project/schemas
308
output=Path("../models/generated.py")
309
)
310
```
311
312
### Input Format Detection
313
```python
314
from datamodel_code_generator import infer_input_type, is_openapi, is_schema
315
316
# Automatic detection
317
content = '{"openapi": "3.0.0", "info": {"title": "API"}}'
318
file_type = infer_input_type(content)
319
print(file_type) # InputFileType.OpenAPI
320
321
# Manual checking
322
import json
323
data = json.loads(content)
324
print(is_openapi(data)) # True
325
print(is_schema(data)) # False
326
```
327
328
### Error Handling
329
```python
330
from datamodel_code_generator import generate, Error, InvalidClassNameError
331
332
try:
333
generate(
334
input_=Path("schema.json"),
335
output=Path("models.py")
336
)
337
except InvalidClassNameError as e:
338
print(f"Invalid class name: {e.class_name}")
339
# Handle class name normalization
340
except Error as e:
341
print(f"Generation error: {e.message}")
342
# Handle general generation errors
343
except FileNotFoundError:
344
print("Schema file not found")
345
# Handle file system errors
346
```
347
348
### Debug Tracing
349
```python
350
from datamodel_code_generator import enable_debug_message, snooper_to_methods
351
352
# Enable debug tracing (requires debug extra)
353
try:
354
enable_debug_message()
355
356
# Now generation will include detailed tracing
357
generate(input_=schema_path, output=output_path)
358
359
except Exception as e:
360
print(f"Debug mode requires: pip install 'datamodel-code-generator[debug]'")
361
```
362
363
### Custom Error Handling
364
```python
365
from datamodel_code_generator import Error
366
367
class CustomGenerationError(Error):
368
"""Custom error for application-specific handling."""
369
370
def __init__(self, context: str, original_error: Exception):
371
self.context = context
372
self.original_error = original_error
373
message = f"Generation failed in {context}: {original_error}"
374
super().__init__(message)
375
376
# Usage in application code
377
try:
378
generate(input_=schema_path, output=output_path)
379
except Error as e:
380
raise CustomGenerationError("schema processing", e)
381
```
382
383
### Input Validation Helper
384
```python
385
from datamodel_code_generator import is_openapi, is_schema, load_yaml
386
from pathlib import Path
387
388
def validate_schema_file(path: Path) -> str:
389
"""Validate and identify schema file type."""
390
try:
391
content = path.read_text()
392
data = load_yaml(content)
393
394
if is_openapi(data):
395
return "OpenAPI 3.x specification"
396
elif is_schema(data):
397
return "JSON Schema"
398
else:
399
return "Raw data (will be converted to JSON Schema)"
400
401
except Exception as e:
402
raise Error(f"Invalid schema file: {e}")
403
404
# Usage
405
try:
406
schema_type = validate_schema_file(Path("api.yaml"))
407
print(f"Detected: {schema_type}")
408
except Error as e:
409
print(f"Validation failed: {e.message}")
410
```