"""Base converter abstract class.""" from abc import ABC, abstractmethod from pathlib import Path from typing import Any, Dict, Optional class ConversionError(Exception): """Base exception for conversion errors.""" pass class BaseConverter(ABC): """Abstract base class for format converters.""" FORMAT_NAME: str = "" FILE_EXTENSIONS: list[str] = [] @abstractmethod def read(self, source: str | Path) -> Dict[str, Any]: """Read and parse a configuration file.""" @abstractmethod def write(self, data: Dict[str, Any], target: str | Path) -> None: """Write configuration data to a file.""" @abstractmethod def parse(self, content: str) -> Dict[str, Any]: """Parse configuration content from a string.""" @abstractmethod def format(self, data: Dict[str, Any]) -> str: """Format configuration data to a string.""" @classmethod def get_converter(cls, fmt: str) -> "BaseConverter": """Get converter instance by format name.""" from config_converter.converters.json_converter import JsonConverter from config_converter.converters.yaml_converter import YamlConverter from config_converter.converters.toml_converter import TomlConverter from config_converter.converters.ini_converter import IniConverter converters: Dict[str, type[BaseConverter]] = { "json": JsonConverter, "yaml": YamlConverter, "yml": YamlConverter, "toml": TomlConverter, "ini": IniConverter, } fmt_lower = fmt.lower() if fmt_lower not in converters: raise ConversionError( f"Unsupported format: {fmt}. Supported formats: {list(converters.keys())}" ) return converters[fmt_lower]() @classmethod def get_supported_formats(cls) -> list[str]: """Get list of supported format names.""" return ["json", "yaml", "yml", "toml", "ini"] @classmethod def guess_format(cls, filepath: str | Path) -> Optional[str]: """Guess format from file extension.""" ext = Path(filepath).suffix.lower().lstrip(".") format_map: Dict[str, str] = { "json": "json", "yaml": "yaml", "yml": "yaml", "toml": "toml", "ini": "ini", } return format_map.get(ext)