76 lines
2.4 KiB
Python
76 lines
2.4 KiB
Python
"""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)
|