"""配置加载模块"""
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")),
)