Source code for failextract.core.formatters.yaml

"""YAML output formatter for test failure reports.

This module provides YAML formatting capabilities for test failure data.
YAML output is ideal for configuration-like structured data, human-readable
reports, and integration with systems that prefer YAML over JSON.

Note:
    This formatter requires PyYAML as an optional dependency. Install with:
    pip install failextract[formatters]
"""

from datetime import datetime
from typing import List, Dict, Any

from .base import OutputFormatter


[docs] class YAMLFormatter(OutputFormatter): """YAML output formatter for test failure reports. This formatter produces human-readable YAML output with proper structure and formatting. YAML is often preferred over JSON for configuration files and human-readable data exchange due to its clean syntax and comment support. The formatter requires PyYAML as an optional dependency and will raise a helpful error message if the dependency is not installed. Features: - Clean, human-readable YAML structure - Metadata section with generation time and failure count - Structured failure data with proper YAML formatting - Helpful error message if PyYAML is not installed Example: >>> formatter = YAMLFormatter() >>> failures = [{'test_name': 'test_example', 'timestamp': '2024-01-01'}] >>> yaml_output = formatter.format(failures) >>> print(yaml_output[:50]) test_failure_report: metadata: generated: 2024-01-01 """
[docs] def format(self, failures: List[Dict[str, Any]]) -> str: """Format failure data as YAML. Args: failures: List of failure dictionaries containing test failure information Returns: Human-readable YAML string with structured failure data Raises: ImportError: If PyYAML is not installed with helpful installation message Note: Structures data with metadata section and organized failure information. Uses PyYAML's default_flow_style=False for readable multi-line output. """ try: import yaml except ImportError: raise ImportError( "PyYAML is required for YAML output format. " "Install it with: pip install failextract[formatters]" ) from None # Structure the data for YAML output output_data = { "test_failure_report": { "metadata": { "generated": datetime.now().isoformat(), "total_failures": len(failures), }, "failures": [], } } for failure in failures: failure_data = { "test_info": { "name": failure["test_name"], "module": failure["test_module"], "file": failure["test_file"], "timestamp": failure["timestamp"], }, "exception": { "type": failure["exception_type"], "message": failure["exception_message"], }, "test_source": failure["test_source"], } # Add test arguments if present if failure.get("test_args") and failure["test_args"] != "()": failure_data["test_info"]["args"] = failure["test_args"] if failure.get("test_kwargs") and failure["test_kwargs"] != "{}": failure_data["test_info"]["kwargs"] = failure["test_kwargs"] # Add fixtures if present if failure.get("fixtures"): failure_data["fixtures"] = [] for fixture in failure["fixtures"]: fixture_data = {"name": fixture["name"], "type": fixture["type"]} if fixture["type"] == "builtin": fixture_data["description"] = fixture["description"] else: if fixture.get("scope"): fixture_data["scope"] = fixture["scope"] if fixture.get("file"): fixture_data["file"] = fixture["file"] if fixture.get("dependencies"): fixture_data["dependencies"] = fixture["dependencies"] if fixture.get("source"): fixture_data["source"] = fixture["source"] failure_data["fixtures"].append(fixture_data) # Add extracted code if present if failure.get("extracted_code"): failure_data["extracted_code"] = [] for code in failure["extracted_code"]: code_data = { "file": code["file"], "function": code["function"], "line": code["line"], } if code.get("source"): code_data["source"] = code["source"] if code.get("class_source"): code_data["class_source"] = code["class_source"] if code.get("locals"): code_data["locals"] = code["locals"] failure_data["extracted_code"].append(code_data) # Add full traceback if present if failure.get("exception_traceback"): failure_data["exception"]["traceback"] = failure["exception_traceback"] output_data["test_failure_report"]["failures"].append(failure_data) return yaml.dump( output_data, default_flow_style=False, sort_keys=False, indent=2 )
[docs] def get_extension(self) -> str: """Get the file extension for YAML files. Returns: File extension '.yaml' """ return ".yaml"