"""数据源协议 + 注册表。 定义 DataSource 契约,并提供全局注册表供路由层分发。 每个比赛数据源实现该协议,注册后即可通过统一入口调度。 注: injuries 是球员级独立领域(写 Injury 表),不遵循此协议。 """ from __future__ import annotations from typing import Protocol from src.db.base import AsyncSession class DataSource(Protocol): """比赛数据源契约:抓取 → 规范化 → 入库。""" @property def name(self) -> str: """数据源标识名(用于路由/日志)。""" ... async def ingest(self, db: AsyncSession, **kwargs) -> dict: """执行完整采集流程,返回统计。""" ... # ── 注册表 ── _SOURCES: dict[str, DataSource] = {} def register(source: DataSource) -> DataSource: """装饰器:将数据源注册到全局注册表。""" _SOURCES[source.name] = source return source def get_source(name: str) -> DataSource: """按名获取数据源。""" if not _SOURCES: _load_sources() if name not in _SOURCES: raise ValueError(f"未知数据源: {name}") return _SOURCES[name] def list_sources() -> list[str]: """列出所有已注册数据源名。""" if not _SOURCES: _load_sources() return list(_SOURCES.keys()) def _load_sources() -> None: """延迟导入数据源触发 @register(避免循环导入)。""" from src.data.bzzoiro import BzzoiroSource # noqa: F811 from src.data.understat import UnderstatSource # noqa: F811 # 保持向后兼容:模块加载时尝试加载(但不再强制) try: _load_sources() except Exception: pass