Type stubs for PyYAML, a full-featured YAML framework for Python
Exception classes for handling various YAML processing errors with position information and detailed error messages. PyYAML provides a comprehensive error hierarchy for diagnosing YAML processing issues.
Foundation exception classes that provide basic error information and position tracking.
class YAMLError(Exception):
"""
Base exception for all YAML-related errors.
All other YAML exceptions inherit from this class, allowing
for broad exception handling.
"""
class MarkedYAMLError(YAMLError):
"""
YAML error with position information for precise error location.
Attributes:
- context: str | None - Description of the error context
- context_mark: Mark | None - Position where context was detected
- problem: str | None - Description of the specific problem
- problem_mark: Mark | None - Position where problem was detected
- note: str | None - Additional information about the error
"""Mark class for tracking positions in YAML streams with detailed location information.
class Mark:
"""
Represents a position in a YAML stream for error reporting.
Attributes:
- name: str - Name of the input source (filename, '<string>', etc.)
- index: int - Character index from start of stream
- line: int - Line number (0-based)
- column: int - Column number (0-based)
- buffer: str | None - Buffer content around the position
- pointer: int - Pointer position in buffer
"""
def get_snippet(self, indent: int = 4, max_length: int = 75) -> str:
"""
Get a code snippet showing the error location.
Parameters:
- indent: Number of spaces to indent the snippet
- max_length: Maximum length of the snippet line
Returns:
- Formatted code snippet with error pointer
"""Specialized exception classes for different types of YAML processing errors.
class ScannerError(MarkedYAMLError):
"""
Error during YAML token scanning phase.
Raised when the scanner encounters invalid YAML syntax
at the character level (e.g., invalid escape sequences,
unterminated strings).
"""
class ParserError(MarkedYAMLError):
"""
Error during YAML parsing phase.
Raised when the parser encounters invalid YAML structure
(e.g., malformed documents, invalid indentation).
"""
class ComposerError(MarkedYAMLError):
"""
Error during YAML composition phase.
Raised when the composer encounters issues with node
relationships (e.g., duplicate anchors, invalid aliases).
"""
class ConstructorError(MarkedYAMLError):
"""
Error during YAML construction phase.
Raised when the constructor cannot build Python objects
from YAML nodes (e.g., unknown tags, invalid values).
"""
class RepresenterError(YAMLError):
"""
Error during YAML representation phase.
Raised when the representer cannot convert Python objects
to YAML nodes (e.g., unrepresentable objects).
"""
class SerializerError(YAMLError):
"""
Error during YAML serialization phase.
Raised when the serializer encounters issues converting
nodes to events.
"""
class EmitterError(YAMLError):
"""
Error during YAML emission phase.
Raised when the emitter cannot convert events to YAML text
(e.g., encoding issues, stream write errors).
"""
class ReaderError(YAMLError):
"""
Error during YAML reading phase.
Raised when the reader encounters issues with the input stream
(e.g., encoding problems, unreadable characters).
Attributes:
- name: Any - Source name
- character: Any - Problem character
- position: Any - Character position
- encoding: Any - Stream encoding
- reason: Any - Error reason
"""
class ResolverError(YAMLError):
"""
Error during YAML tag resolution phase.
Raised when the resolver encounters issues determining
appropriate tags for values.
"""import yaml
def safe_load_yaml(yaml_string):
"""Load YAML with comprehensive error handling."""
try:
return yaml.safe_load(yaml_string)
except yaml.YAMLError as e:
print(f"YAML Error: {e}")
return None
# Test with invalid YAML
invalid_yaml = """
name: John
age: 30
items:
- item1
- item2
- nested_wrong # Invalid indentation
"""
result = safe_load_yaml(invalid_yaml)import yaml
def detailed_yaml_error_handler(yaml_string):
"""Handle YAML errors with detailed position information."""
try:
return yaml.safe_load(yaml_string)
except yaml.MarkedYAMLError as e:
print(f"YAML Error: {e}")
if e.context_mark:
print(f"Context at line {e.context_mark.line + 1}, "
f"column {e.context_mark.column + 1}")
if e.problem_mark:
print(f"Problem at line {e.problem_mark.line + 1}, "
f"column {e.problem_mark.column + 1}")
# Show code snippet with error location
snippet = e.problem_mark.get_snippet()
if snippet:
print("Code snippet:")
print(snippet)
if e.problem:
print(f"Problem: {e.problem}")
if e.context:
print(f"Context: {e.context}")
return None
except yaml.YAMLError as e:
print(f"General YAML Error: {e}")
return None
# Test with malformed YAML
malformed_yaml = """
name: "John Doe
age: 30
"""
result = detailed_yaml_error_handler(malformed_yaml)import yaml
def handle_specific_errors(yaml_string):
"""Handle different types of YAML errors specifically."""
try:
return yaml.safe_load(yaml_string)
except yaml.ScannerError as e:
print(f"Scanner Error - Invalid YAML syntax: {e}")
# Handle character-level syntax errors
except yaml.ParserError as e:
print(f"Parser Error - Invalid YAML structure: {e}")
# Handle structural errors
except yaml.ConstructorError as e:
print(f"Constructor Error - Cannot build objects: {e}")
# Handle object construction errors
except yaml.ComposerError as e:
print(f"Composer Error - Node relationship issues: {e}")
# Handle anchor/alias errors
except yaml.YAMLError as e:
print(f"Other YAML Error: {e}")
# Handle any other YAML errors
return None
# Test various error types
test_cases = [
# Scanner error - unterminated string
'name: "unterminated string',
# Parser error - invalid indentation
'''
items:
- item1
- item2 # Wrong indentation
''',
# Constructor error - unknown tag
'value: !!unknown_tag some_value',
# Composer error - duplicate anchor
'''
item1: &anchor value1
item2: &anchor value2 # Duplicate anchor
'''
]
for i, test_yaml in enumerate(test_cases):
print(f"\nTest case {i + 1}:")
handle_specific_errors(test_yaml)import yaml
def validate_yaml_file(filename):
"""Validate a YAML file and report any errors."""
try:
with open(filename, 'r', encoding='utf-8') as file:
documents = list(yaml.safe_load_all(file))
print(f"✓ Valid YAML file with {len(documents)} document(s)")
return documents
except FileNotFoundError:
print(f"✗ File not found: {filename}")
except yaml.ReaderError as e:
print(f"✗ Reading error: {e}")
print(f" Encoding: {e.encoding}")
print(f" Position: {e.position}")
except yaml.ScannerError as e:
print(f"✗ Scanner error at line {e.problem_mark.line + 1}: {e.problem}")
except yaml.ParserError as e:
print(f"✗ Parser error at line {e.problem_mark.line + 1}: {e.problem}")
except yaml.YAMLError as e:
print(f"✗ YAML error: {e}")
return None
def safe_yaml_merge(*yaml_strings):
"""Safely merge multiple YAML strings, skipping invalid ones."""
merged_data = {}
for i, yaml_str in enumerate(yaml_strings):
try:
data = yaml.safe_load(yaml_str)
if isinstance(data, dict):
merged_data.update(data)
print(f"✓ Merged YAML string {i + 1}")
else:
print(f"⚠ YAML string {i + 1} is not a mapping, skipped")
except yaml.YAMLError as e:
print(f"✗ YAML string {i + 1} error: {e}")
continue
return merged_data
# Usage examples
yaml_strings = [
'name: John\nage: 30', # Valid
'city: "New York\nstate: NY', # Invalid - unterminated string
'skills:\n - Python\n - YAML', # Valid
'invalid: !!bad_tag value' # Invalid - unknown tag
]
result = safe_yaml_merge(*yaml_strings)
print(f"Final merged data: {result}")import yaml
import logging
class YAMLConfigLoader:
"""Configuration loader with robust YAML error handling."""
def __init__(self, logger=None):
self.logger = logger or logging.getLogger(__name__)
def load_config(self, config_path, default_config=None):
"""Load configuration with fallback to defaults on errors."""
try:
with open(config_path, 'r') as file:
config = yaml.safe_load(file)
self.logger.info(f"Successfully loaded config from {config_path}")
return config
except FileNotFoundError:
self.logger.warning(f"Config file not found: {config_path}")
except yaml.YAMLError as e:
self.logger.error(f"YAML error in {config_path}: {e}")
# Log detailed error information for debugging
if hasattr(e, 'problem_mark') and e.problem_mark:
mark = e.problem_mark
self.logger.error(f"Error at line {mark.line + 1}, column {mark.column + 1}")
except Exception as e:
self.logger.error(f"Unexpected error loading {config_path}: {e}")
# Return default config if loading failed
if default_config is not None:
self.logger.info("Using default configuration")
return default_config
else:
raise RuntimeError(f"Could not load configuration from {config_path}")
# Usage
loader = YAMLConfigLoader()
config = loader.load_config(
'app_config.yaml',
default_config={'debug': False, 'port': 8080}
)Install with Tessl CLI
npx tessl i tessl/pypi-types-pyyaml