新增独立 xiaobai-datahub 服务(SQLite WAL、Tushare 盘后发布、/v1 契约和管理后台),不改现站页面与数据链路。 Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: multica-agent <github@multica.ai>
48 lines
1.4 KiB
Python
48 lines
1.4 KiB
Python
from __future__ import annotations
|
|
|
|
from abc import ABC, abstractmethod
|
|
from typing import Any
|
|
|
|
|
|
class AdapterError(RuntimeError):
|
|
pass
|
|
|
|
|
|
class MarketAdapter(ABC):
|
|
"""Uniform adapter: probe / fetch / normalize. Realtime adapters may be stubs in P0."""
|
|
|
|
name: str = "base"
|
|
|
|
@abstractmethod
|
|
def probe(self) -> dict[str, Any]:
|
|
"""Liveness check. Must not leak credentials."""
|
|
|
|
@abstractmethod
|
|
def fetch(self, dataset: str, params: dict[str, Any]) -> list[dict[str, Any]]:
|
|
"""Return provider-native rows (pre-canonical)."""
|
|
|
|
@abstractmethod
|
|
def normalize(self, dataset: str, rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
"""Map provider-native rows onto hub canonical fields."""
|
|
|
|
|
|
class ReservedAdapter(MarketAdapter):
|
|
"""Placeholder for a later free/licensed source. Does not pull data in P0."""
|
|
|
|
def __init__(self, name: str) -> None:
|
|
self.name = name
|
|
|
|
def probe(self) -> dict[str, Any]:
|
|
return {
|
|
"provider": self.name,
|
|
"configured": False,
|
|
"state": "reserved",
|
|
"message": "适配器位已预留,本阶段不接入",
|
|
}
|
|
|
|
def fetch(self, dataset: str, params: dict[str, Any]) -> list[dict[str, Any]]:
|
|
raise AdapterError(f"{self.name} 适配器本阶段未接入")
|
|
|
|
def normalize(self, dataset: str, rows: list[dict[str, Any]]) -> list[dict[str, Any]]:
|
|
return []
|