"""配置加载模块""" from dataclasses import dataclass, field from pathlib import Path import yaml @dataclass class DeviceConfig: model: str = "kobo-clara-bw" width: int = 1072 height: int = 1448 color: bool = False @dataclass class ProcessingConfig: split_double_page: bool = True crop_whitespace: bool = True resize: bool = True grayscale: bool = True enhance_contrast: bool = True contrast_factor: float = 1.2 @dataclass class DownloadConfig: concurrent: int = 3 retry: int = 3 delay: float = 1.0 @dataclass class TransferConfig: method: str = "usb" calibre_host: str = "localhost" calibre_port: int = 8080 @dataclass class SchedulerConfig: interval: int = 3600 auto_push: bool = False @dataclass class AppConfig: device: DeviceConfig = field(default_factory=DeviceConfig) sources: list[str] = field(default_factory=list) processing: ProcessingConfig = field(default_factory=ProcessingConfig) download: DownloadConfig = field(default_factory=DownloadConfig) transfer: TransferConfig = field(default_factory=TransferConfig) scheduler: SchedulerConfig = field(default_factory=SchedulerConfig) def _dict_to_dataclass(cls, data: dict): """将字典映射到 dataclass,忽略多余字段。""" if data is None: return cls() valid_fields = {f.name for f in cls.__dataclass_fields__.values()} filtered = {k: v for k, v in data.items() if k in valid_fields} return cls(**filtered) def load_config(config_path: str | Path | None = None) -> AppConfig: """加载配置文件,未指定时查找项目根目录的 config.yaml。""" if config_path is None: config_path = Path("config.yaml") else: config_path = Path(config_path) if not config_path.exists(): return AppConfig() with open(config_path, encoding="utf-8") as f: raw = yaml.safe_load(f) or {} return AppConfig( device=_dict_to_dataclass(DeviceConfig, raw.get("device")), sources=raw.get("sources", []), processing=_dict_to_dataclass(ProcessingConfig, raw.get("processing")), download=_dict_to_dataclass(DownloadConfig, raw.get("download")), transfer=_dict_to_dataclass(TransferConfig, raw.get("transfer")), scheduler=_dict_to_dataclass(SchedulerConfig, raw.get("scheduler")), )